Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/ctrace/BinaryLocator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ export async function locateBinary(extensionPath: string): Promise<string | null
return null;
}

/**
* Looks for a ctrace binary on PATH (e.g. built from source on macOS, where
* no prebuilt release exists). Returns the resolved path, or null.
*/
export async function locateBinaryOnPath(): Promise<string | null> {
for (const dir of (process.env.PATH || '').split(path.delimiter).filter(Boolean)) {
for (const name of ['ctrace', 'coretrace']) {
const candidate = path.join(dir, name);
if (await isExecutableFile(candidate)) {
return candidate;
}
}
}
return null;
}

async function isExecutableFile(filePath: string): Promise<boolean> {
try {
const stat = await fs.promises.stat(filePath);
Expand Down
14 changes: 8 additions & 6 deletions src/ctrace/BinaryUpdater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as path from 'path';
import * as tar from 'tar';
import { pipeline } from 'stream/promises';
import { Readable, Transform } from 'stream';
import { locateBinary } from './BinaryLocator';
import { locateBinary, locateBinaryOnPath } from './BinaryLocator';

const REPO_LATEST_RELEASE_URL = 'https://api.github.com/repos/CoreTrace/coretrace/releases/latest';

Expand Down Expand Up @@ -53,15 +53,17 @@ async function doEnsureBinary(context: vscode.ExtensionContext, output: vscode.O
const FAILURE_BACKOFF = 60 * 1000;

// If we have a cached binary and checked recently, avoid spamming the GitHub API.
if (downloadedBinaryPath && now - lastCheck < TWELVE_HOURS) {
return downloadedBinaryPath;
// A PATH binary counts too: platforms without a release asset (macOS) would otherwise hit the API on every scan.
const knownBinary = downloadedBinaryPath ?? await locateBinaryOnPath();
if (knownBinary && now - lastCheck < TWELVE_HOURS) {
return knownBinary;
}

// When there is no cached binary, keep retrying with a short backoff.
// This avoids a 12-hour lockout if the very first download fails.
if (!downloadedBinaryPath && now - lastFailedCheck < FAILURE_BACKOFF) {
output.appendLine('Skipping update check due to recent failure backoff.');
return await locateBinary(context.extensionUri.fsPath);
return await locateBinaryOnPath();
}

try {
Expand Down Expand Up @@ -121,8 +123,8 @@ async function doEnsureBinary(context: vscode.ExtensionContext, output: vscode.O
const cachedBin = await getExtractedBinaryPath(binDir);
if (cachedBin) return cachedBin;

// Fallback to bundled
return await locateBinary(context.extensionUri.fsPath);
// Bundled was already checked at the top; last resort is a user-installed ctrace.
return await locateBinaryOnPath();
Comment on lines +126 to +127

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Throttle release checks when using the PATH binary

When macOS has a working PATH-installed binary but the release response has no Darwin asset, every analysis reaches this fallback only after another GitHub API request. Although line 105 records coretrace-last-update-check, the earlier throttle applies only when downloadedBinaryPath exists, so this successful no-asset case is never throttled; each scan incurs network latency and can exhaust the unauthenticated API limit. Reuse the PATH binary while honoring the update interval, or check it before attempting a download.

Useful? React with 👍 / 👎.

}

function getAssetForPlatform(assets: any[]): { name: string; url: string } | null {
Expand Down
11 changes: 9 additions & 2 deletions src/ctrace/DependencyInstaller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,14 +235,21 @@ elif command -v zypper >/dev/null 2>&1; then
elif command -v apk >/dev/null 2>&1; then
echo "Detected Alpine Linux (apk)."
apk add --no-cache cppcheck flawfinder build-base git cmake python3 py3-pip curl || true
elif command -v brew >/dev/null 2>&1; then
echo "Detected macOS (Homebrew)."
# Homebrew refuses to run as root, so install as the invoking user.
sudo -u "\${SUDO_USER:-$(id -un)}" brew install cppcheck flawfinder cmake python3 || true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Install IKOS in the Homebrew branch

On a clean macOS installation, this command installs cppcheck, flawfinder, cmake, and Python but never installs IKOS; the later setup only links ikos when it already exists. Consequently, post-install verification adds ikos to the missing list and installDependencies reports failure, so the new Homebrew path cannot complete the advertised all-analyzer installation unless the user had separately installed IKOS.

Useful? React with 👍 / 👎.

# IKOS is only published through NASA's tap (builds LLVM deps, can take a while).
sudo -u "\${SUDO_USER:-$(id -un)}" brew install nasa-sw-vnv/core/ikos || true
else
echo "Warning: Unrecognized package manager. Please ensure git, g++, make, cmake, python3, and curl are installed."
fi

echo "=== [2/5] Creating CoreTrace tools directory structure... ==="
USER_HOME="$CORETRACE_USER_HOME"
if [ -z "$USER_HOME" ] && [ -n "$SUDO_USER" ]; then
USER_HOME=$(getent passwd "$SUDO_USER" | cut -d: -f6)
# getent does not exist on macOS; tilde expansion works everywhere.
USER_HOME=$(eval echo "~$SUDO_USER")
fi
if [ -z "$USER_HOME" ]; then
USER_HOME="$HOME"
Expand Down Expand Up @@ -344,7 +351,7 @@ fi
# Ensure permissions
TOOLS_OWNER="$CORETRACE_USER_NAME"
if [ -z "$TOOLS_OWNER" ]; then TOOLS_OWNER="$SUDO_USER"; fi
if [ -n "$TOOLS_OWNER" ]; then chown -R "$TOOLS_OWNER:$TOOLS_OWNER" "$TOOLS_DIR" 2>/dev/null || true; fi
if [ -n "$TOOLS_OWNER" ]; then chown -R "$TOOLS_OWNER" "$TOOLS_DIR" 2>/dev/null || true; fi
chmod -R 755 "$TOOLS_DIR" 2>/dev/null || true

echo "=== All CoreTrace dependencies installed and verified successfully! ==="
Expand Down
5 changes: 4 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,11 @@ export function activate(context: vscode.ExtensionContext) {
if (!p) {
const extPath = context.extensionUri.fsPath;
const globalStorage = context.globalStorageUri.fsPath;
const hint = process.platform === 'darwin'
? '\nCoreTrace publishes no prebuilt macOS binary: build it from https://github.com/CoreTrace/coretrace and put `ctrace` on your PATH.'
: '';
vscode.window.showErrorMessage(
`Ctrace binary could not be found or downloaded. Checked: \n- ${globalStorage}/bin\n- ${extPath}\nSee the "Ctrace" Output channel for details.`
`Ctrace binary could not be found or downloaded. Checked: \n- ${globalStorage}/bin\n- ${extPath}\n- PATH${hint}\nSee the "Ctrace" Output channel for details.`
);
}
return p;
Expand Down
Loading