mirror of
https://gitee.com/spark-store-project/spark-store
synced 2026-06-22 14:13:49 +08:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e16acbd0a5 | |||
| 8a5f8d154f | |||
| 8c8b53fc29 | |||
| c50655c106 | |||
| 4b37aa4da4 | |||
| ce5de692f7 | |||
| 3d4af0c492 | |||
| c39b25e393 | |||
| 2086152aa5 | |||
| f8f112a782 | |||
| 6a9091b2ec | |||
| 994dbaf9b9 | |||
| 9c9f0b6076 |
+20
@@ -23,3 +23,23 @@
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
2. https://github.com/elysia-best/apm-app-store MulanPSL-2.0
|
||||
|
||||
Copyright (c) 2026-present The Spark Project Contributors
|
||||
|
||||
apm-store is licensed under Mulan PSL v2.
|
||||
|
||||
You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
|
||||
You may obtain a copy of Mulan PSL v2 at:
|
||||
|
||||
http://license.coscl.org.cn/MulanPSL2
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
|
||||
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
|
||||
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the Mulan PSL v2 for more details.
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BrowserWindow, dialog, ipcMain, WebContents } from "electron";
|
||||
import { ipcMain, WebContents } from "electron";
|
||||
import { spawn, ChildProcess, exec } from "node:child_process";
|
||||
import { promisify } from "node:util";
|
||||
import fs from "node:fs";
|
||||
@@ -114,25 +114,6 @@ const checkSparkAvailable = async (): Promise<boolean> => {
|
||||
return found;
|
||||
};
|
||||
|
||||
/** 提权执行 shell-caller aptss install apm 安装 APM,安装后需用户重启电脑 */
|
||||
const runInstallApm = async (superUserCmd: string): Promise<boolean> => {
|
||||
const execCommand = superUserCmd || SHELL_CALLER_PATH;
|
||||
const execParams = superUserCmd
|
||||
? [SHELL_CALLER_PATH, "aptss", "install", "apm"]
|
||||
: [SHELL_CALLER_PATH, "aptss", "install", "apm"];
|
||||
logger.info(`执行安装 APM: ${execCommand} ${execParams.join(" ")}`);
|
||||
const { code, stdout, stderr } = await runCommandCapture(
|
||||
execCommand,
|
||||
execParams,
|
||||
);
|
||||
if (code !== 0) {
|
||||
logger.error({ code, stdout, stderr }, "安装 APM 失败");
|
||||
return false;
|
||||
}
|
||||
logger.info("安装 APM 完成");
|
||||
return true;
|
||||
};
|
||||
|
||||
const parseUpgradableList = (output: string) => {
|
||||
const apps: Array<{
|
||||
pkgname: string;
|
||||
@@ -215,62 +196,24 @@ ipcMain.on("queue-install", async (event, download_json) => {
|
||||
const execParams = [];
|
||||
const downloadDir = `/tmp/spark-store/download/${pkgname}`;
|
||||
|
||||
// APM 应用:若本机没有 apm 命令,弹窗提示并可选提权安装 APM(安装后需重启电脑)
|
||||
// APM 应用:若本机没有 apm 命令,通知前端弹窗引导安装 APM
|
||||
if (origin === "apm") {
|
||||
const hasApm = await checkApmAvailable();
|
||||
if (!hasApm) {
|
||||
const win = BrowserWindow.fromWebContents(webContents);
|
||||
const { response } = await dialog.showMessageBox(win ?? undefined, {
|
||||
type: "question",
|
||||
title: "需要安装 APM",
|
||||
message: "此应用需要使用 APM 安装。",
|
||||
detail:
|
||||
"APM是星火应用商店的容器包管理器,安装APM后方可安装此应用,是否确认安装?",
|
||||
buttons: ["确认", "取消"],
|
||||
defaultId: 0,
|
||||
cancelId: 1,
|
||||
});
|
||||
if (response !== 0) {
|
||||
webContents.send("trigger-apm-install-dialog");
|
||||
webContents.send("install-complete", {
|
||||
id,
|
||||
success: false,
|
||||
time: Date.now(),
|
||||
exitCode: -1,
|
||||
message: JSON.stringify({
|
||||
message: "用户取消安装 APM,无法继续安装此应用",
|
||||
message: "未安装 APM,无法继续安装此应用",
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
}),
|
||||
});
|
||||
return;
|
||||
}
|
||||
const installApmOk = await runInstallApm(superUserCmd);
|
||||
if (!installApmOk) {
|
||||
webContents.send("install-complete", {
|
||||
id,
|
||||
success: false,
|
||||
time: Date.now(),
|
||||
exitCode: -1,
|
||||
message: JSON.stringify({
|
||||
message: "安装 APM 失败,请检查网络或权限后重试",
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
}),
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
// 安装APM成功,提示用户已安装成功,需要重启后方可展示应用
|
||||
await dialog.showMessageBox(win ?? undefined, {
|
||||
type: "info",
|
||||
title: "APM 安装成功",
|
||||
message: "恭喜您,APM 已成功安装",
|
||||
detail:
|
||||
"恭喜您,APM 已成功安装!您的应用已在安装中~\n首次安装APM后,需要重启电脑后方可在启动器展示应用。您可在应用安装完毕后择机重启电脑\n若您需要立即使用应用,可在应用安装后先在应用商店中打开您的应用。",
|
||||
buttons: ["确定"],
|
||||
defaultId: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (origin === "spark") {
|
||||
@@ -462,8 +405,8 @@ async function processNextInQueue() {
|
||||
|
||||
sendStatus("downloading");
|
||||
|
||||
// 下载重试逻辑:每次超时时间递增,最多3次
|
||||
const timeoutList = [3000, 5000, 15000]; // 第一次3秒,第二次5秒,第三次15秒
|
||||
// 下载重试逻辑:共10次,5次3秒,3次5秒,2次10秒
|
||||
const timeoutList = [3000, 3000, 3000, 3000, 3000, 5000, 5000, 5000, 10000, 10000];
|
||||
let retryCount = 0;
|
||||
let downloadSuccess = false;
|
||||
|
||||
@@ -1089,51 +1032,11 @@ ipcMain.handle("check-spark-available", async () => {
|
||||
});
|
||||
|
||||
// 显示 APM 安装对话框(在点击安装按钮时提前检查)
|
||||
// 前端已改为 Vue 弹窗,此后端处理仅作为兜底
|
||||
ipcMain.handle("show-apm-install-dialog", async (event) => {
|
||||
const webContents = event.sender;
|
||||
const win = BrowserWindow.fromWebContents(webContents);
|
||||
const superUserCmd = await checkSuperUserCommand();
|
||||
|
||||
const { response } = await dialog.showMessageBox(win ?? undefined, {
|
||||
type: "question",
|
||||
title: "需要安装 APM",
|
||||
message: "此应用需要使用 APM 安装。",
|
||||
detail:
|
||||
"APM 是星火应用商店的软件包兼容工具,此应用使用星火 APM 提供支持,安装APM后方可安装此应用,是否确认安装?",
|
||||
buttons: ["确认", "取消"],
|
||||
defaultId: 0,
|
||||
cancelId: 1,
|
||||
});
|
||||
|
||||
if (response !== 0) {
|
||||
webContents.send("trigger-apm-install-dialog");
|
||||
return { success: false, cancelled: true };
|
||||
}
|
||||
|
||||
const installApmOk = await runInstallApm(superUserCmd);
|
||||
if (!installApmOk) {
|
||||
await dialog.showMessageBox(win ?? undefined, {
|
||||
type: "error",
|
||||
title: "安装失败",
|
||||
message: "安装 APM 失败",
|
||||
detail: "请检查网络或权限后重试",
|
||||
buttons: ["确定"],
|
||||
defaultId: 0,
|
||||
});
|
||||
return { success: false, cancelled: false };
|
||||
}
|
||||
|
||||
// 安装APM成功,提示用户已安装成功,需要重启后方可展示应用
|
||||
await dialog.showMessageBox(win ?? undefined, {
|
||||
type: "info",
|
||||
title: "APM 安装成功",
|
||||
message: "恭喜您,APM 已成功安装",
|
||||
detail:
|
||||
"恭喜您,APM 已成功安装!\n首次安装APM后,需要重启电脑后方可使用全部功能。您可在应用安装完毕后择机重启电脑。",
|
||||
buttons: ["确定"],
|
||||
defaultId: 0,
|
||||
});
|
||||
|
||||
return { success: true, cancelled: false };
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
||||
@@ -104,8 +104,8 @@ export const downloadPackage = async ({
|
||||
|
||||
onStatus?.("downloading");
|
||||
|
||||
// 下载重试逻辑:每次超时时间递增,最多3次
|
||||
const timeoutList = [3000, 5000, 15000];
|
||||
// 下载重试逻辑:共10次,5次3秒,3次5秒,2次10秒
|
||||
const timeoutList = [3000, 3000, 3000, 3000, 3000, 5000, 5000, 5000, 10000, 10000];
|
||||
let retryCount = 0;
|
||||
let downloadSuccess = false;
|
||||
|
||||
|
||||
@@ -376,7 +376,9 @@ export const loadUpdateCenterItems = async (
|
||||
storeFilter: StoreFilter = "both",
|
||||
runCommand: UpdateCenterCommandRunner = runCommandCapture,
|
||||
): Promise<UpdateCenterLoadItemsResult> => {
|
||||
console.log(`[UpdateCenter] loadUpdateCenterItems called with storeFilter=${storeFilter}`);
|
||||
console.log(
|
||||
`[UpdateCenter] loadUpdateCenterItems called with storeFilter=${storeFilter}`,
|
||||
);
|
||||
const [sparkEnabled, apmEnabled] = await Promise.all([
|
||||
isSourceEnabled(storeFilter, "spark")
|
||||
? isCommandAvailable(runCommand, "aptss")
|
||||
@@ -385,7 +387,9 @@ export const loadUpdateCenterItems = async (
|
||||
? isCommandAvailable(runCommand, "apm")
|
||||
: Promise.resolve(false),
|
||||
]);
|
||||
console.log(`[UpdateCenter] sparkEnabled=${sparkEnabled}, apmEnabled=${apmEnabled}`);
|
||||
console.log(
|
||||
`[UpdateCenter] sparkEnabled=${sparkEnabled}, apmEnabled=${apmEnabled}`,
|
||||
);
|
||||
|
||||
const [aptssResult, apmResult, aptssInstalledResult, apmInstalledResult] =
|
||||
await Promise.all([
|
||||
@@ -409,10 +413,18 @@ export const loadUpdateCenterItems = async (
|
||||
: Promise.resolve({ code: 0, stdout: "", stderr: "" }),
|
||||
]);
|
||||
|
||||
console.log(`[UpdateCenter] aptssResult: code=${aptssResult.code}, stdout=${aptssResult.stdout.substring(0, 500)}, stderr=${aptssResult.stderr.substring(0, 500)}`);
|
||||
console.log(`[UpdateCenter] apmResult: code=${apmResult.code}, stdout=${apmResult.stdout.substring(0, 500)}, stderr=${apmResult.stderr.substring(0, 500)}`);
|
||||
console.log(`[UpdateCenter] aptssInstalledResult: code=${aptssInstalledResult.code}, stdout=${aptssInstalledResult.stdout.substring(0, 500)}`);
|
||||
console.log(`[UpdateCenter] apmInstalledResult: code=${apmInstalledResult.code}, stdout=${apmInstalledResult.stdout.substring(0, 500)}`);
|
||||
console.log(
|
||||
`[UpdateCenter] aptssResult: code=${aptssResult.code}, stdout=${aptssResult.stdout.substring(0, 500)}, stderr=${aptssResult.stderr.substring(0, 500)}`,
|
||||
);
|
||||
console.log(
|
||||
`[UpdateCenter] apmResult: code=${apmResult.code}, stdout=${apmResult.stdout.substring(0, 500)}, stderr=${apmResult.stderr.substring(0, 500)}`,
|
||||
);
|
||||
console.log(
|
||||
`[UpdateCenter] aptssInstalledResult: code=${aptssInstalledResult.code}, stdout=${aptssInstalledResult.stdout.substring(0, 500)}`,
|
||||
);
|
||||
console.log(
|
||||
`[UpdateCenter] apmInstalledResult: code=${apmInstalledResult.code}, stdout=${apmInstalledResult.stdout.substring(0, 500)}`,
|
||||
);
|
||||
|
||||
const aptssAvailable =
|
||||
sparkEnabled && (aptssResult.code === 0 || aptssInstalledResult.code === 0);
|
||||
@@ -438,8 +450,14 @@ export const loadUpdateCenterItems = async (
|
||||
apmEnabled && apmResult.code === 0
|
||||
? parseApmUpgradableOutput(apmResult.stdout)
|
||||
: [];
|
||||
console.log(`[UpdateCenter] parsed aptssItems count=${aptssItems.length}`, aptssItems.map((i) => `${i.pkgname} ${i.currentVersion}->${i.nextVersion}`));
|
||||
console.log(`[UpdateCenter] parsed apmItems count=${apmItems.length}`, apmItems.map((i) => `${i.pkgname} ${i.currentVersion}->${i.nextVersion}`));
|
||||
console.log(
|
||||
`[UpdateCenter] parsed aptssItems count=${aptssItems.length}`,
|
||||
aptssItems.map((i) => `${i.pkgname} ${i.currentVersion}->${i.nextVersion}`),
|
||||
);
|
||||
console.log(
|
||||
`[UpdateCenter] parsed apmItems count=${apmItems.length}`,
|
||||
apmItems.map((i) => `${i.pkgname} ${i.currentVersion}->${i.nextVersion}`),
|
||||
);
|
||||
|
||||
const installedSources = buildInstalledSourceMap(
|
||||
aptssAvailable && aptssInstalledResult.code === 0
|
||||
@@ -461,15 +479,26 @@ export const loadUpdateCenterItems = async (
|
||||
? enrichApmItems(categorizedApmItems, runCommand)
|
||||
: Promise.resolve({ items: [], warnings: [] }),
|
||||
]);
|
||||
console.log(`[UpdateCenter] enrichedAptssItems: count=${enrichedAptssItems.items.length}, warnings=${enrichedAptssItems.warnings.length}`, enrichedAptssItems.warnings);
|
||||
console.log(`[UpdateCenter] enrichedApmItems: count=${enrichedApmItems.items.length}, warnings=${enrichedApmItems.warnings.length}`, enrichedApmItems.warnings);
|
||||
console.log(
|
||||
`[UpdateCenter] enrichedAptssItems: count=${enrichedAptssItems.items.length}, warnings=${enrichedAptssItems.warnings.length}`,
|
||||
enrichedAptssItems.warnings,
|
||||
);
|
||||
console.log(
|
||||
`[UpdateCenter] enrichedApmItems: count=${enrichedApmItems.items.length}, warnings=${enrichedApmItems.warnings.length}`,
|
||||
enrichedApmItems.warnings,
|
||||
);
|
||||
|
||||
const mergedItems = mergeUpdateSources(
|
||||
enrichItemIcons(enrichedAptssItems.items),
|
||||
enrichItemIcons(enrichedApmItems.items),
|
||||
installedSources,
|
||||
);
|
||||
console.log(`[UpdateCenter] mergedItems count=${mergedItems.length}`, mergedItems.map((i) => `${i.pkgname} (${i.source}) ${i.currentVersion}->${i.nextVersion}`));
|
||||
console.log(
|
||||
`[UpdateCenter] mergedItems count=${mergedItems.length}`,
|
||||
mergedItems.map(
|
||||
(i) => `${i.pkgname} (${i.source}) ${i.currentVersion}->${i.nextVersion}`,
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
items: mergedItems,
|
||||
|
||||
@@ -263,16 +263,26 @@ const compareVersions = (left: string, right: string): number => {
|
||||
export const parseAptssUpgradableOutput = (
|
||||
output: string,
|
||||
): UpdateCenterItem[] => {
|
||||
console.log(`[UpdateCenter] parseAptssUpgradableOutput input (first 1000 chars): ${output.substring(0, 1000)}`);
|
||||
console.log(
|
||||
`[UpdateCenter] parseAptssUpgradableOutput input (first 1000 chars): ${output.substring(0, 1000)}`,
|
||||
);
|
||||
const result = parseUpgradableOutput(output, "aptss");
|
||||
console.log(`[UpdateCenter] parseAptssUpgradableOutput result count=${result.length}`);
|
||||
console.log(
|
||||
`[UpdateCenter] parseAptssUpgradableOutput result count=${result.length}`,
|
||||
);
|
||||
return result;
|
||||
};
|
||||
|
||||
export const parseApmUpgradableOutput = (output: string): UpdateCenterItem[] => {
|
||||
console.log(`[UpdateCenter] parseApmUpgradableOutput input (first 1000 chars): ${output.substring(0, 1000)}`);
|
||||
export const parseApmUpgradableOutput = (
|
||||
output: string,
|
||||
): UpdateCenterItem[] => {
|
||||
console.log(
|
||||
`[UpdateCenter] parseApmUpgradableOutput input (first 1000 chars): ${output.substring(0, 1000)}`,
|
||||
);
|
||||
const result = parseUpgradableOutput(output, "apm");
|
||||
console.log(`[UpdateCenter] parseApmUpgradableOutput result count=${result.length}`);
|
||||
console.log(
|
||||
`[UpdateCenter] parseApmUpgradableOutput result count=${result.length}`,
|
||||
);
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -283,10 +293,14 @@ export const parsePrintUrisOutput = (
|
||||
"downloadUrl" | "fileName" | "size" | "sha512"
|
||||
> | null => {
|
||||
const trimmed = output.trim();
|
||||
console.log(`[UpdateCenter] parsePrintUrisOutput input (first 500 chars): ${trimmed.substring(0, 500)}`);
|
||||
console.log(
|
||||
`[UpdateCenter] parsePrintUrisOutput input (first 500 chars): ${trimmed.substring(0, 500)}`,
|
||||
);
|
||||
const match = trimmed.match(PRINT_URIS_PATTERN);
|
||||
if (!match) {
|
||||
console.log(`[UpdateCenter] parsePrintUrisOutput: no match found for pattern ${PRINT_URIS_PATTERN}`);
|
||||
console.log(
|
||||
`[UpdateCenter] parsePrintUrisOutput: no match found for pattern ${PRINT_URIS_PATTERN}`,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -166,7 +166,9 @@ export const createUpdateCenterService = (
|
||||
storeFilter: StoreFilter = currentStoreFilter,
|
||||
): Promise<UpdateCenterServiceState> => {
|
||||
currentStoreFilter = storeFilter;
|
||||
console.log(`[UpdateCenter] service.refresh called with storeFilter=${storeFilter}`);
|
||||
console.log(
|
||||
`[UpdateCenter] service.refresh called with storeFilter=${storeFilter}`,
|
||||
);
|
||||
queue.startRefresh();
|
||||
emit();
|
||||
|
||||
@@ -176,11 +178,16 @@ export const createUpdateCenterService = (
|
||||
const loadedItems = normalizeLoadedItems(
|
||||
await options.loadItems(currentStoreFilter),
|
||||
);
|
||||
console.log(`[UpdateCenter] loadItems returned: items=${loadedItems.items.length}, warnings=${loadedItems.warnings.length}`, loadedItems.warnings);
|
||||
console.log(
|
||||
`[UpdateCenter] loadItems returned: items=${loadedItems.items.length}, warnings=${loadedItems.warnings.length}`,
|
||||
loadedItems.warnings,
|
||||
);
|
||||
const items = sortIgnoredItems(
|
||||
applyIgnoredEntries(loadedItems.items, ignoredEntries),
|
||||
);
|
||||
console.log(`[UpdateCenter] after applying ignored: items=${items.length}`);
|
||||
console.log(
|
||||
`[UpdateCenter] after applying ignored: items=${items.length}`,
|
||||
);
|
||||
queue.setItems(items);
|
||||
queue.finishRefresh(loadedItems.warnings);
|
||||
return emit();
|
||||
|
||||
@@ -98,6 +98,10 @@ logger.info("User Agent: " + getUserAgent());
|
||||
|
||||
/** 根据启动参数 --no-apm / --no-spark 决定只展示的来源 */
|
||||
function getStoreFilterFromArgv(): "spark" | "apm" | "both" {
|
||||
if (process.arch === "loong64") {
|
||||
// Currently loong64 only have spark support
|
||||
return "spark";
|
||||
} else {
|
||||
const argv = process.argv;
|
||||
const noApm = argv.includes("--no-apm");
|
||||
const noSpark = argv.includes("--no-spark");
|
||||
@@ -105,6 +109,7 @@ function getStoreFilterFromArgv(): "spark" | "apm" | "both" {
|
||||
if (noApm) return "spark";
|
||||
if (noSpark) return "apm";
|
||||
return "both";
|
||||
}
|
||||
}
|
||||
|
||||
ipcMain.handle("get-store-filter", (): "spark" | "apm" | "both" =>
|
||||
|
||||
Generated
+17
-15
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "spark-store",
|
||||
"version": "5.0.0beta4",
|
||||
"version": "5.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "spark-store",
|
||||
"version": "5.0.0beta4",
|
||||
"version": "5.0.0",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@tailwindcss/vite": "^4.1.18",
|
||||
@@ -28,7 +28,7 @@
|
||||
"@vue/test-utils": "^2.4.3",
|
||||
"conventional-changelog": "^7.1.1",
|
||||
"conventional-changelog-angular": "^8.1.0",
|
||||
"electron": "^40.0.0",
|
||||
"electron": "^39.2.7",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-prettier": "^5.5.5",
|
||||
@@ -4870,15 +4870,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron": {
|
||||
"version": "40.8.5",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-40.8.5.tgz",
|
||||
"integrity": "sha512-pgTY/VPQKaiU4sTjfU96iyxCXrFm4htVPCMRT4b7q9ijNTRgtLmLvcmzp2G4e7xDrq9p7OLHSmu1rBKFf6Y1/A==",
|
||||
"version": "39.2.7",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-39.2.7.tgz",
|
||||
"integrity": "sha512-KU0uFS6LSTh4aOIC3miolcbizOFP7N1M46VTYVfqIgFiuA2ilfNaOHLDS9tCMvwwHRowAsvqBrh9NgMXcTOHCQ==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@electron/get": "^2.0.0",
|
||||
"@types/node": "^24.9.0",
|
||||
"@types/node": "^22.7.7",
|
||||
"extract-zip": "^2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
@@ -4889,19 +4889,21 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron/node_modules/@types/node": {
|
||||
"version": "24.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz",
|
||||
"integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==",
|
||||
"version": "22.19.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.17.tgz",
|
||||
"integrity": "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~7.16.0"
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/electron/node_modules/undici-types": {
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
||||
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
|
||||
"dev": true
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
|
||||
+3
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "spark-store",
|
||||
"version": "5.0.0",
|
||||
"version": "5.1.0",
|
||||
"main": "dist-electron/main/index.js",
|
||||
"description": "Client for Spark App Store",
|
||||
"author": "elysia-best <elysia-best@simplelinux.cn.eu.org>",
|
||||
@@ -30,6 +30,7 @@
|
||||
"build:vite": "vue-tsc --noEmit && vite build --mode production",
|
||||
"build:rpm": "vue-tsc --noEmit && vite build --mode production && electron-builder --config electron-builder.yml --linux rpm",
|
||||
"build:deb": "vue-tsc --noEmit && vite build --mode production && electron-builder --config electron-builder.yml --linux deb",
|
||||
"build:deb-loong64": "vue-tsc --noEmit && vite build --mode production && env ELECTRON_MIRROR=https://github.com/darkyzhou/electron-loong64/releases/download/ electron_use_remote_checksums=1 electron-builder --config electron-builder.yml --loong64 --linux deb",
|
||||
"preview": "vite preview --mode debug",
|
||||
"lint": "eslint --ext .ts,.vue src electron",
|
||||
"lint:fix": "eslint --ext .ts,.vue src electron --fix",
|
||||
@@ -56,7 +57,7 @@
|
||||
"@vue/test-utils": "^2.4.3",
|
||||
"conventional-changelog": "^7.1.1",
|
||||
"conventional-changelog-angular": "^8.1.0",
|
||||
"electron": "^40.0.0",
|
||||
"electron": "^39.2.7",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-prettier": "^5.5.5",
|
||||
|
||||
+35
-9
@@ -152,6 +152,12 @@
|
||||
@success="onUninstallSuccess"
|
||||
/>
|
||||
|
||||
<ApmInstallConfirmModal
|
||||
:show="showApmInstallDialog"
|
||||
@close="closeApmInstallDialog"
|
||||
@confirm="confirmApmInstall"
|
||||
/>
|
||||
|
||||
<AboutModal :show="showAboutModal" @close="closeAboutModal" />
|
||||
|
||||
<SettingsModal :show="showSettingsModal" @close="closeSettingsModal" />
|
||||
@@ -173,6 +179,7 @@ import DownloadDetail from "./components/DownloadDetail.vue";
|
||||
import InstalledAppsModal from "./components/InstalledAppsModal.vue";
|
||||
import UpdateCenterModal from "./components/UpdateCenterModal.vue";
|
||||
import UninstallConfirmModal from "./components/UninstallConfirmModal.vue";
|
||||
import ApmInstallConfirmModal from "./components/ApmInstallConfirmModal.vue";
|
||||
import AboutModal from "./components/AboutModal.vue";
|
||||
import SettingsModal from "./components/SettingsModal.vue";
|
||||
import {
|
||||
@@ -181,6 +188,7 @@ import {
|
||||
currentAppSparkInstalled,
|
||||
currentAppApmInstalled,
|
||||
currentStoreMode,
|
||||
showApmInstallDialog,
|
||||
getHybridDefaultOrigin,
|
||||
loadPriorityConfig,
|
||||
} from "./global/storeConfig";
|
||||
@@ -238,8 +246,6 @@ const fetchWithRetry = async <T,>(
|
||||
}
|
||||
};
|
||||
|
||||
const cacheBuster = (url: string) => `${url}?cb=${Date.now()}`;
|
||||
|
||||
// 响应式状态
|
||||
const themeMode = ref<"light" | "dark" | "auto">("auto");
|
||||
const systemIsDark = ref(
|
||||
@@ -401,7 +407,7 @@ const fetchAppFromStore = async (
|
||||
const arch = window.apm_store.arch || "amd64";
|
||||
const finalArch = origin === "spark" ? `${arch}-store` : `${arch}-apm`;
|
||||
const appJsonUrl = `${APM_STORE_BASE_URL}/${finalArch}/${category}/${pkgname}/app.json`;
|
||||
const response = await fetch(cacheBuster(appJsonUrl));
|
||||
const response = await fetch(appJsonUrl);
|
||||
if (!response.ok) return null;
|
||||
const appJson = await response.json();
|
||||
return {
|
||||
@@ -672,7 +678,7 @@ const loadHome = async () => {
|
||||
|
||||
// homelinks.json
|
||||
try {
|
||||
const res = await fetch(cacheBuster(`${base}/homelinks.json`));
|
||||
const res = await fetch(`${base}/homelinks.json`);
|
||||
if (res.ok) {
|
||||
const links = await res.json();
|
||||
const taggedLinks = links.map((l: HomeLink) => ({
|
||||
@@ -687,14 +693,14 @@ const loadHome = async () => {
|
||||
|
||||
// homelist.json
|
||||
try {
|
||||
const res2 = await fetch(cacheBuster(`${base}/homelist.json`));
|
||||
const res2 = await fetch(`${base}/homelist.json`);
|
||||
if (res2.ok) {
|
||||
const lists = await res2.json();
|
||||
for (const item of lists) {
|
||||
if (item.type === "appList" && item.jsonUrl) {
|
||||
try {
|
||||
const url = `${APM_STORE_BASE_URL}/${finalArch}${item.jsonUrl}`;
|
||||
const r = await fetch(cacheBuster(url));
|
||||
const r = await fetch(url);
|
||||
if (r.ok) {
|
||||
const appsJson = await r.json();
|
||||
const rawApps = appsJson || [];
|
||||
@@ -712,7 +718,7 @@ const loadHome = async () => {
|
||||
|
||||
try {
|
||||
const realAppUrl = `${APM_STORE_BASE_URL}/${finalArch}/${baseApp.category}/${baseApp.pkgname}/app.json`;
|
||||
const realRes = await fetch(cacheBuster(realAppUrl));
|
||||
const realRes = await fetch(realAppUrl);
|
||||
if (realRes.ok) {
|
||||
const realApp = await realRes.json();
|
||||
if (realApp.Filename)
|
||||
@@ -966,6 +972,22 @@ const onUninstallSuccess = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const closeApmInstallDialog = () => {
|
||||
showApmInstallDialog.value = false;
|
||||
};
|
||||
|
||||
const confirmApmInstall = async () => {
|
||||
showApmInstallDialog.value = false;
|
||||
closeDetail();
|
||||
await nextTick();
|
||||
const apmApp = apps.value.find((a) => a.pkgname === "apm");
|
||||
if (apmApp) {
|
||||
openDetail(apmApp);
|
||||
} else {
|
||||
searchQuery.value = "apm";
|
||||
}
|
||||
};
|
||||
|
||||
const installCompleteCallback = (pkgname?: string) => {
|
||||
if (currentApp.value && (!pkgname || currentApp.value.pkgname === pkgname)) {
|
||||
checkAppInstalled(currentApp.value);
|
||||
@@ -1081,7 +1103,7 @@ const loadCategories = async () => {
|
||||
const path = `/${finalArch}/categories.json`;
|
||||
|
||||
try {
|
||||
const response = await axiosInstance.get(cacheBuster(path));
|
||||
const response = await axiosInstance.get(path);
|
||||
const data = response.data;
|
||||
Object.keys(data).forEach((key) => {
|
||||
if (categoryData[key]) {
|
||||
@@ -1134,7 +1156,7 @@ const loadApps = async (onFirstBatch?: () => void) => {
|
||||
|
||||
logger.info(`加载分类: ${category} (来源: ${mode})`);
|
||||
const categoryApps = await fetchWithRetry<AppJson[]>(
|
||||
cacheBuster(path),
|
||||
path,
|
||||
);
|
||||
|
||||
const normalizedApps = (categoryApps || []).map((appJson) => ({
|
||||
@@ -1278,6 +1300,10 @@ onMounted(async () => {
|
||||
}
|
||||
});
|
||||
|
||||
window.ipcRenderer.on("trigger-apm-install-dialog", () => {
|
||||
showApmInstallDialog.value = true;
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(
|
||||
"deep-link-install",
|
||||
(_event: IpcRendererEvent, pkgname: string) => {
|
||||
|
||||
@@ -191,7 +191,9 @@ describe("update-center load items", () => {
|
||||
],
|
||||
});
|
||||
|
||||
const result = await loadUpdateCenterItems("both", async (command, args) => {
|
||||
const result = await loadUpdateCenterItems(
|
||||
"both",
|
||||
async (command, args) => {
|
||||
const key = `${command} ${args.join(" ")}`;
|
||||
const match = commandResults.get(key);
|
||||
if (!match) {
|
||||
@@ -199,7 +201,8 @@ describe("update-center load items", () => {
|
||||
}
|
||||
|
||||
return match;
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
expect(result.warnings).toEqual([]);
|
||||
expect(result.items).toContainEqual({
|
||||
@@ -233,7 +236,9 @@ describe("update-center load items", () => {
|
||||
],
|
||||
});
|
||||
|
||||
const result = await loadUpdateCenterItems("both", async (command, args) => {
|
||||
const result = await loadUpdateCenterItems(
|
||||
"both",
|
||||
async (command, args) => {
|
||||
const key = `${command} ${args.join(" ")}`;
|
||||
|
||||
if (key === WHICH_APTSS_KEY) {
|
||||
@@ -287,7 +292,8 @@ describe("update-center load items", () => {
|
||||
}
|
||||
|
||||
throw new Error(`Unexpected command ${key}`);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
expect(result.items).toEqual([
|
||||
{
|
||||
@@ -416,7 +422,9 @@ describe("update-center load items", () => {
|
||||
],
|
||||
});
|
||||
|
||||
const result = await loadUpdateCenterItems("both", async (command, args) => {
|
||||
const result = await loadUpdateCenterItems(
|
||||
"both",
|
||||
async (command, args) => {
|
||||
const key = `${command} ${args.join(" ")}`;
|
||||
|
||||
if (key === WHICH_APTSS_KEY) {
|
||||
@@ -461,7 +469,8 @@ describe("update-center load items", () => {
|
||||
}
|
||||
|
||||
throw new Error(`Unexpected command ${key}`);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
expect(result.items).toEqual([
|
||||
{
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<Transition
|
||||
enter-active-class="duration-200 ease-out"
|
||||
enter-from-class="opacity-0 scale-95"
|
||||
enter-to-class="opacity-100 scale-100"
|
||||
leave-active-class="duration-150 ease-in"
|
||||
leave-from-class="opacity-100 scale-100"
|
||||
leave-to-class="opacity-0 scale-95"
|
||||
>
|
||||
<div
|
||||
v-if="show"
|
||||
class="fixed inset-0 z-[80] flex items-center justify-center bg-slate-900/70 p-4"
|
||||
@click.self="handleClose"
|
||||
>
|
||||
<div
|
||||
class="relative w-full max-w-lg overflow-hidden rounded-3xl border border-white/10 bg-white/95 p-6 shadow-2xl dark:border-slate-800 dark:bg-slate-900"
|
||||
>
|
||||
<div class="mb-6 flex items-center gap-4">
|
||||
<div
|
||||
class="flex h-16 w-16 items-center justify-center rounded-2xl bg-gradient-to-br from-brand/20 to-brand/10 shadow-inner dark:from-brand/20 dark:to-brand/10"
|
||||
>
|
||||
<i class="fas fa-box-open text-2xl text-brand"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl font-bold text-slate-900 dark:text-white">
|
||||
需要安装 APM
|
||||
</h3>
|
||||
<p class="text-sm text-slate-500 dark:text-slate-400">
|
||||
APM 是星火应用商店的软件包兼容工具,此应用使用星火 APM 提供支持。
|
||||
</p>
|
||||
<p class="mt-1 text-sm text-slate-500 dark:text-slate-400">
|
||||
是否前往商店安装
|
||||
<span class="font-semibold text-slate-700 dark:text-slate-200"
|
||||
>APM</span
|
||||
>
|
||||
?
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-end gap-3">
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-xl border border-slate-200 bg-white px-4 py-2 text-sm font-medium text-slate-600 transition hover:bg-slate-50 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-300 dark:hover:bg-slate-700"
|
||||
@click="handleClose"
|
||||
>
|
||||
取消
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex items-center gap-2 rounded-xl bg-gradient-to-r from-brand to-brand-dark px-4 py-2 text-sm font-semibold text-white shadow-lg shadow-brand/30 transition hover:-translate-y-0.5"
|
||||
@click="handleConfirm"
|
||||
>
|
||||
<i class="fas fa-download"></i>
|
||||
前往安装
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
show: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "close"): void;
|
||||
(e: "confirm"): void;
|
||||
}>();
|
||||
|
||||
const handleClose = () => {
|
||||
emit("close");
|
||||
};
|
||||
|
||||
const handleConfirm = () => {
|
||||
emit("confirm");
|
||||
};
|
||||
</script>
|
||||
@@ -62,7 +62,7 @@
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex items-center gap-2 rounded-2xl border border-slate-200/70 px-4 py-2 text-sm font-semibold text-slate-600 transition hover:bg-slate-50 disabled:opacity-40 dark:border-slate-700 dark:text-slate-200"
|
||||
class="inline-flex items-center gap-2 rounded-2xl border border-slate-200/70 px-4 py-2 text-sm font-semibold text-slate-600 transition hover:bg-slate-50 disabled:opacity-40 dark:border-slate-700 dark:text-slate-200 dark:hover:bg-slate-800"
|
||||
:disabled="loading"
|
||||
@click="$emit('refresh')"
|
||||
>
|
||||
@@ -71,7 +71,7 @@
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex h-10 w-10 items-center justify-center rounded-full border border-slate-200/70 text-slate-500 transition hover:text-slate-900 dark:border-slate-700"
|
||||
class="inline-flex h-10 w-10 items-center justify-center rounded-full border border-slate-200/70 text-slate-500 transition hover:text-slate-900 dark:hover:text-white dark:border-slate-700 dark:hover:bg-slate-800"
|
||||
@click="$emit('close')"
|
||||
aria-label="关闭"
|
||||
>
|
||||
|
||||
@@ -47,7 +47,9 @@
|
||||
v-if="store.loading.value && store.filteredItems.value.length === 0"
|
||||
class="flex min-h-0 flex-1 items-center justify-center p-6"
|
||||
>
|
||||
<div class="flex flex-col items-center gap-3 text-slate-500 dark:text-slate-400">
|
||||
<div
|
||||
class="flex flex-col items-center gap-3 text-slate-500 dark:text-slate-400"
|
||||
>
|
||||
<i class="fas fa-circle-notch fa-spin text-3xl"></i>
|
||||
<p class="text-sm">正在检查更新…</p>
|
||||
</div>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<button
|
||||
type="button"
|
||||
aria-label="关闭"
|
||||
class="inline-flex h-11 w-11 items-center justify-center rounded-full border border-slate-200/70 text-slate-500 transition hover:text-slate-900 dark:border-slate-700 dark:text-slate-300"
|
||||
class="inline-flex h-10 w-10 items-center justify-center rounded-full border border-slate-200/70 text-slate-500 transition hover:text-slate-900 dark:hover:text-white dark:border-slate-700 dark:hover:bg-slate-800"
|
||||
@click="$emit('request-close')"
|
||||
>
|
||||
<i class="fas fa-xmark"></i>
|
||||
|
||||
@@ -11,6 +11,7 @@ export const APM_STORE_STATS_BASE_URL: string =
|
||||
export const currentApp = ref<App | null>(null);
|
||||
export const currentAppSparkInstalled = ref(false);
|
||||
export const currentAppApmInstalled = ref(false);
|
||||
export const showApmInstallDialog = ref(false);
|
||||
|
||||
export const currentStoreMode = ref<StoreMode>("hybrid");
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
currentApp,
|
||||
currentAppSparkInstalled,
|
||||
currentAppApmInstalled,
|
||||
showApmInstallDialog,
|
||||
} from "../global/storeConfig";
|
||||
import { APM_STORE_BASE_URL } from "../global/storeConfig";
|
||||
import { downloads, getNextDownloadId } from "../global/downloadStatus";
|
||||
@@ -28,16 +29,10 @@ export const handleInstall = async (appObj?: App) => {
|
||||
if (targetApp.origin === "apm") {
|
||||
const hasApm = await window.ipcRenderer.invoke("check-apm-available");
|
||||
if (!hasApm) {
|
||||
// 发送事件到主进程显示 APM 安装对话框
|
||||
const { success, cancelled } = await window.ipcRenderer.invoke(
|
||||
"show-apm-install-dialog",
|
||||
);
|
||||
if (!success || cancelled) {
|
||||
// 用户取消或未安装成功,不继续安装应用
|
||||
showApmInstallDialog.value = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
downloads.value.find(
|
||||
@@ -119,16 +114,10 @@ export const handleUpgrade = async (app: App) => {
|
||||
if (app.origin === "apm") {
|
||||
const hasApm = await window.ipcRenderer.invoke("check-apm-available");
|
||||
if (!hasApm) {
|
||||
// 发送事件到主进程显示 APM 安装对话框
|
||||
const { success, cancelled } = await window.ipcRenderer.invoke(
|
||||
"show-apm-install-dialog",
|
||||
);
|
||||
if (!success || cancelled) {
|
||||
// 用户取消或未安装成功,不继续更新应用
|
||||
showApmInstallDialog.value = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
downloads.value.find(
|
||||
|
||||
@@ -3,7 +3,7 @@ Dir::Cache::archives "/var/cache/apt/archives";
|
||||
Dir::Cache "/var/lib/aptss/";
|
||||
Dir::Etc::SourceParts "/opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/";
|
||||
Dir::State::lists "/var/lib/aptss/lists/";
|
||||
|
||||
APT::Sandbox::User "root";
|
||||
APT::Get::Fix-Broken true;
|
||||
APT::Get::List-Cleanup="0";
|
||||
|
||||
|
||||
@@ -83,6 +83,9 @@ cleanup_aptfast()
|
||||
if [ -n "$LISTTEMP" ] && [ -d "$LISTTEMP" ]; then
|
||||
rm -rf "$LISTTEMP"
|
||||
fi
|
||||
if [ -n "$tmpdir" ] && [ -d "$tmpdir" ]; then
|
||||
rm -rf "$tmpdir"
|
||||
fi
|
||||
}
|
||||
exit_cleanup_state()
|
||||
{
|
||||
@@ -120,11 +123,8 @@ _create_lock()
|
||||
# unlock and remove the lock file
|
||||
_remove_lock()
|
||||
{
|
||||
# Only unlock if lock file exists (was created by _create_lock)
|
||||
if [ -f "$LCK_FILE.lock" ]; then
|
||||
flock -u "$LCK_FD" 2>/dev/null
|
||||
rm -f "$LCK_FILE.lock"
|
||||
fi
|
||||
}
|
||||
|
||||
# Search for known options and decide if root privileges are needed.
|
||||
@@ -134,7 +134,6 @@ for argument in "$@"; do
|
||||
case "$argument" in
|
||||
upgrade | full-upgrade | install | dist-upgrade | build-dep)
|
||||
option="install"
|
||||
_create_lock
|
||||
;;
|
||||
clean | autoclean)
|
||||
option="clean"
|
||||
@@ -313,6 +312,9 @@ https_proxy=
|
||||
[ "$TMP_http_proxy" = "$TMP_RANDOM" ] || http_proxy="$TMP_http_proxy"
|
||||
[ "$TMP_https_proxy" = "$TMP_RANDOM" ] || https_proxy="$TMP_https_proxy"
|
||||
|
||||
if [ "$option" == "install" ]; then
|
||||
_create_lock
|
||||
fi
|
||||
|
||||
# Disable colors if not executed in terminal.
|
||||
if [ ! -t 1 ]; then
|
||||
@@ -456,22 +458,12 @@ get_uris(){
|
||||
exit "$CLEANUP_STATE"
|
||||
fi
|
||||
prepare_auth
|
||||
local tmpdir
|
||||
tmpdir=$(mktemp -d) || {
|
||||
msg "Failed to create tmp dir" "warning"
|
||||
msg "无法创建临时目录" "warning"
|
||||
exit 1
|
||||
|
||||
|
||||
}
|
||||
|
||||
cleanup_tmpdir() {
|
||||
if [ -n "$tmpdir" ] && [ -d "$tmpdir" ]; then
|
||||
rm -rf "$tmpdir"
|
||||
fi
|
||||
}
|
||||
trap cleanup_tmpdir EXIT
|
||||
|
||||
## --print-uris format is:
|
||||
# 'fileurl' filename filesize checksum_hint:filechecksum
|
||||
# 修改:process_package函数增加第二个参数表示当前线程的临时输出文件
|
||||
@@ -824,9 +816,6 @@ elif [ "$option" == "download" ]; then
|
||||
"${_APTMGR}" "$@"
|
||||
fi
|
||||
|
||||
# Clean up temporary directory for download command
|
||||
cleanup_aptfast
|
||||
|
||||
elif [ "$option" == "source" ]; then
|
||||
msg
|
||||
msg "Working... this may take a while." "normal"
|
||||
@@ -853,9 +842,6 @@ elif [ "$option" == "source" ]; then
|
||||
# dpkg-source -x "$(basename "$srcfile")"
|
||||
#done < "$DLLIST"
|
||||
|
||||
# Clean up temporary directory for source command
|
||||
cleanup_aptfast
|
||||
|
||||
# Execute package manager directly if unknown options are passed.
|
||||
else
|
||||
"${_APTMGR}" "${APT_SCRIPT_WARNING[@]}" "$@"
|
||||
|
||||
Reference in New Issue
Block a user