This commit is contained in:
2026-02-09 09:32:20 +00:00
commit f23ced9c47
22 changed files with 9064 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
import * as path from 'path';
import * as fs from 'fs';
import * as smolToml from 'smol-toml';
import { FsHelpers } from '../mod_fs/index.js';
export interface ICargoWorkspaceInfo {
isWorkspace: boolean;
rustDir: string;
binTargets: string[];
}
export class CargoConfig {
private rustDir: string;
constructor(rustDir: string) {
this.rustDir = rustDir;
}
public async parse(): Promise<ICargoWorkspaceInfo> {
const cargoTomlPath = path.join(this.rustDir, 'Cargo.toml');
const content = await fs.promises.readFile(cargoTomlPath, 'utf-8');
const parsed = smolToml.parse(content);
const isWorkspace = !!(parsed as any).workspace;
let binTargets: string[] = [];
if (isWorkspace) {
binTargets = await this.collectWorkspaceBinTargets(parsed);
} else {
binTargets = this.collectCrateBinTargets(parsed, this.rustDir);
}
return {
isWorkspace,
rustDir: this.rustDir,
binTargets,
};
}
private async collectWorkspaceBinTargets(parsed: any): Promise<string[]> {
const members: string[] = parsed.workspace?.members || [];
const binTargets: string[] = [];
for (const member of members) {
const memberDir = path.join(this.rustDir, member);
const memberCargoToml = path.join(memberDir, 'Cargo.toml');
if (!(await FsHelpers.fileExists(memberCargoToml))) {
continue;
}
const memberContent = await fs.promises.readFile(memberCargoToml, 'utf-8');
const memberParsed = smolToml.parse(memberContent);
const memberBins = this.collectCrateBinTargets(memberParsed, memberDir);
binTargets.push(...memberBins);
}
return binTargets;
}
private collectCrateBinTargets(parsed: any, crateDir: string): string[] {
const binTargets: string[] = [];
// Check for explicit [[bin]] entries
if (Array.isArray(parsed.bin)) {
for (const bin of parsed.bin) {
if (bin.name) {
binTargets.push(bin.name);
}
}
}
// If no [[bin]] but package has a name and src/main.rs exists, use package name
if (binTargets.length === 0 && parsed.package?.name) {
const mainRsPath = path.join(crateDir, 'src', 'main.rs');
// Use sync check since this is called during parsing
try {
const stat = fs.statSync(mainRsPath);
if (stat.isFile()) {
binTargets.push(parsed.package.name);
}
} catch {
// No main.rs, not a binary crate
}
}
return binTargets;
}
}

View File

@@ -0,0 +1,59 @@
import * as plugins from '../plugins.js';
export interface ICargoRunResult {
success: boolean;
exitCode: number;
stdout: string;
}
export class CargoRunner {
private shell: plugins.smartshell.Smartshell;
private rustDir: string;
constructor(rustDir: string) {
this.rustDir = rustDir;
this.shell = new plugins.smartshell.Smartshell({
executor: 'bash',
});
}
public async checkCargoInstalled(): Promise<boolean> {
const result = await this.shell.execSilent('cargo --version');
return result.exitCode === 0;
}
public async getCargoVersion(): Promise<string> {
const result = await this.shell.execSilent('cargo --version');
return result.stdout.trim();
}
public async build(options: { debug?: boolean; clean?: boolean } = {}): Promise<ICargoRunResult> {
if (options.clean) {
console.log('Cleaning previous build...');
await this.clean();
}
const profile = options.debug ? '' : ' --release';
const command = `cd ${this.rustDir} && cargo build${profile}`;
console.log(`Running: cargo build${profile}`);
const result = await this.shell.exec(command);
return {
success: result.exitCode === 0,
exitCode: result.exitCode,
stdout: result.stdout,
};
}
public async clean(): Promise<ICargoRunResult> {
const command = `cd ${this.rustDir} && cargo clean`;
const result = await this.shell.exec(command);
return {
success: result.exitCode === 0,
exitCode: result.exitCode,
stdout: result.stdout,
};
}
}

2
ts/mod_cargo/index.ts Normal file
View File

@@ -0,0 +1,2 @@
export { CargoConfig } from './classes.cargoconfig.js';
export { CargoRunner } from './classes.cargorunner.js';