karajan-code 4.1.3 → 4.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -44,6 +44,12 @@ export function osvScannerSource(platform = process.platform, arch = process.arc
|
|
|
44
44
|
*/
|
|
45
45
|
export function semgrepFallback(available = {}) {
|
|
46
46
|
if (available.docker) return { via: "docker", command: "docker pull semgrep/semgrep" };
|
|
47
|
+
// KJC-BUG-0120 (issue #1256): on Debian/Ubuntu-like systems the system
|
|
48
|
+
// Python is externally managed (PEP 668) and often ships without pip at
|
|
49
|
+
// all — `python3 -m pip install --user` is guaranteed to fail there.
|
|
50
|
+
// pipx must come from the distro's own package manager.
|
|
51
|
+
if (available.apt) return { via: "apt", command: "sudo apt update && sudo apt install -y pipx && pipx install semgrep" };
|
|
52
|
+
if (available.dnf) return { via: "dnf", command: "sudo dnf install -y pipx && pipx install semgrep" };
|
|
47
53
|
return { via: "pipx", command: "python3 -m pip install --user pipx && pipx install semgrep" };
|
|
48
54
|
}
|
|
49
55
|
|
|
@@ -4,7 +4,6 @@ import { fileURLToPath } from "node:url";
|
|
|
4
4
|
import { printBanner } from "../banner.js";
|
|
5
5
|
import { ANSI } from "./formatters.js";
|
|
6
6
|
|
|
7
|
-
// TODO: i18n display messages
|
|
8
7
|
const DISPLAY_PKG_PATH = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../../package.json");
|
|
9
8
|
const DISPLAY_VERSION = JSON.parse(readFileSync(DISPLAY_PKG_PATH, "utf8")).version;
|
|
10
9
|
|
|
@@ -80,8 +80,13 @@ export async function getInstallHint(tool, available = null) {
|
|
|
80
80
|
for (const { manager, command } of candidates) {
|
|
81
81
|
if (avail[manager]) return { command, manager, manualUrl: MANUAL_URLS[tool] };
|
|
82
82
|
}
|
|
83
|
-
// Nothing matched —
|
|
84
|
-
//
|
|
83
|
+
// Nothing matched — suggest a recipe that actually works on this system.
|
|
84
|
+
// KJC-BUG-0120 (issue #1256): distro-aware fallbacks first (PEP 668 makes
|
|
85
|
+
// the generic pip bootstrap fail on Debian/Ubuntu); these are display-only
|
|
86
|
+
// (manager: null), never auto-run — sudo stays in the user's hands.
|
|
87
|
+
for (const { when, command } of DISTRO_FALLBACKS[tool] || []) {
|
|
88
|
+
if (avail[when]) return { command, manager: null, manualUrl: MANUAL_URLS[tool] };
|
|
89
|
+
}
|
|
85
90
|
const first = candidates[0];
|
|
86
91
|
return {
|
|
87
92
|
command: first ? first.command : null,
|
|
@@ -90,6 +95,13 @@ export async function getInstallHint(tool, available = null) {
|
|
|
90
95
|
};
|
|
91
96
|
}
|
|
92
97
|
|
|
98
|
+
const DISTRO_FALLBACKS = {
|
|
99
|
+
semgrep: [
|
|
100
|
+
{ when: "apt", command: "sudo apt update && sudo apt install -y pipx && pipx install semgrep" },
|
|
101
|
+
{ when: "dnf", command: "sudo dnf install -y pipx && pipx install semgrep" },
|
|
102
|
+
],
|
|
103
|
+
};
|
|
104
|
+
|
|
93
105
|
const INSTALL_CANDIDATES = {
|
|
94
106
|
semgrep: [
|
|
95
107
|
{ manager: "pipx", command: "pipx install semgrep" },
|
|
@@ -25,7 +25,9 @@ const OS_COMMANDS = {
|
|
|
25
25
|
win32: ["winget install Git.Git"],
|
|
26
26
|
},
|
|
27
27
|
semgrep: {
|
|
28
|
-
|
|
28
|
+
// PEP 668 (#1256): system Python is externally managed on modern
|
|
29
|
+
// distros — pipx comes from the distro package manager, never from pip.
|
|
30
|
+
linux: ["sudo apt update && sudo apt install -y pipx && pipx install semgrep # Debian/Ubuntu", "sudo dnf install -y pipx && pipx install semgrep # Fedora/RHEL"],
|
|
29
31
|
darwin: ["brew install semgrep"],
|
|
30
32
|
win32: ["python -m pip install --user semgrep"],
|
|
31
33
|
},
|
|
@@ -75,10 +77,11 @@ export function renderPendingBlock(pending, { platform = process.platform, retry
|
|
|
75
77
|
for (const r of pending) {
|
|
76
78
|
const why = r.error ? `install failed: ${r.error}` : r.reason || "no automatic route on this machine";
|
|
77
79
|
lines.push(` ▸ ${r.tool} (${why})`);
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
const os = osCommandsFor(r.tool, platform);
|
|
81
|
+
const own = r.commands ?? (r.command ? [r.command] : null) ?? (r.suggested ? [r.suggested] : null);
|
|
82
|
+
// A FAILED install must not be re-suggested verbatim (#1256: the pip
|
|
83
|
+
// route that just broke) — the curated per-OS route goes first there.
|
|
84
|
+
const commands = (r.action === "failed" ? (os.length > 0 ? os : own) : (own ?? (os.length > 0 ? os : null)))
|
|
82
85
|
?? [`see ${r.manualUrl || "the tool's install docs"}`];
|
|
83
86
|
for (const c of commands) lines.push(` ${c}`);
|
|
84
87
|
lines.push("");
|