@git.zone/tsrust 1.5.0 → 1.6.0

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/.smartconfig.json CHANGED
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "@git.zone/cli": {
3
+ "schemaVersion": 2,
3
4
  "projectType": "npm",
4
5
  "module": {
5
6
  "githost": "code.foss.global",
@@ -20,12 +21,20 @@
20
21
  },
21
22
  "release": {
22
23
  "targets": {
24
+ "git": {
25
+ "enabled": true,
26
+ "remote": "origin",
27
+ "pushBranch": true,
28
+ "pushTags": true
29
+ },
23
30
  "npm": {
31
+ "enabled": true,
24
32
  "registries": [
25
33
  "https://verdaccio.lossless.digital",
26
34
  "https://registry.npmjs.org"
27
35
  ],
28
- "accessLevel": "public"
36
+ "accessLevel": "public",
37
+ "alreadyPublished": "success"
29
38
  }
30
39
  }
31
40
  }
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@git.zone/tsrust',
6
- version: '1.5.0',
6
+ version: '1.6.0',
7
7
  description: 'A tool for compiling Rust projects, detecting Cargo workspaces, building with cargo, and placing binaries in a conventional dist_rust directory.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxrQkFBa0I7SUFDeEIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLGtKQUFrSjtDQUNoSyxDQUFBIn0=
@@ -16,11 +16,14 @@ export declare class CargoRunner {
16
16
  target?: string;
17
17
  crtStatic?: boolean;
18
18
  rustflags?: string[];
19
+ targetDir?: string;
19
20
  }): Promise<ICargoRunResult>;
20
21
  private shellQuote;
21
22
  /**
22
23
  * Ensures a rustup target is installed. If not present, installs it via `rustup target add`.
23
24
  */
24
25
  ensureTarget(triple: string): Promise<void>;
25
- clean(): Promise<ICargoRunResult>;
26
+ clean(options?: {
27
+ targetDir?: string;
28
+ }): Promise<ICargoRunResult>;
26
29
  }
@@ -21,7 +21,7 @@ export class CargoRunner {
21
21
  async build(options = {}) {
22
22
  if (options.clean) {
23
23
  console.log('Cleaning previous build...');
24
- await this.clean();
24
+ await this.clean({ targetDir: options.targetDir });
25
25
  }
26
26
  // crt-static may only be injected together with an explicit --target:
27
27
  // without one, cargo applies RUSTFLAGS to host artifacts too, and rustc
@@ -39,8 +39,9 @@ export class CargoRunner {
39
39
  rustflags.unshift('-C', 'target-feature=+crt-static');
40
40
  }
41
41
  const rustflagsPrefix = rustflags.length ? `RUSTFLAGS=${this.shellQuote(rustflags.join(' '))} ` : '';
42
- const command = `${this.envPrefix}cd ${this.rustDir} && ${rustflagsPrefix}cargo build${profile}${targetFlag}`;
43
- console.log(`Running: ${rustflagsPrefix}cargo build${profile}${targetFlag}`);
42
+ const targetDirPrefix = options.targetDir ? `CARGO_TARGET_DIR=${this.shellQuote(options.targetDir)} ` : '';
43
+ const command = `${this.envPrefix}cd ${this.rustDir} && ${targetDirPrefix}${rustflagsPrefix}cargo build${profile}${targetFlag}`;
44
+ console.log(`Running: ${targetDirPrefix}${rustflagsPrefix}cargo build${profile}${targetFlag}`);
44
45
  const result = await this.shell.exec(command);
45
46
  return {
46
47
  success: result.exitCode === 0,
@@ -66,8 +67,9 @@ export class CargoRunner {
66
67
  throw new Error(`Failed to install rustup target ${triple}`);
67
68
  }
68
69
  }
69
- async clean() {
70
- const command = `${this.envPrefix}cd ${this.rustDir} && cargo clean`;
70
+ async clean(options = {}) {
71
+ const targetDirPrefix = options.targetDir ? `CARGO_TARGET_DIR=${this.shellQuote(options.targetDir)} ` : '';
72
+ const command = `${this.envPrefix}cd ${this.rustDir} && ${targetDirPrefix}cargo clean`;
71
73
  const result = await this.shell.exec(command);
72
74
  return {
73
75
  success: result.exitCode === 0,
@@ -76,4 +78,4 @@ export class CargoRunner {
76
78
  };
77
79
  }
78
80
  }
79
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5jYXJnb3J1bm5lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL21vZF9jYXJnby9jbGFzc2VzLmNhcmdvcnVubmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBUXpDLE1BQU0sT0FBTyxXQUFXO0lBQ2QsS0FBSyxDQUFnQztJQUNyQyxPQUFPLENBQVM7SUFDaEIsU0FBUyxDQUFTO0lBRTFCLFlBQVksT0FBZSxFQUFFLFlBQW9CLEVBQUU7UUFDakQsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7UUFDM0IsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDO1lBQzdDLFFBQVEsRUFBRSxNQUFNO1NBQ2pCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTSxLQUFLLENBQUMsbUJBQW1CO1FBQzlCLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxpQkFBaUIsQ0FBQyxDQUFDO1FBQy9FLE9BQU8sTUFBTSxDQUFDLFFBQVEsS0FBSyxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUVNLEtBQUssQ0FBQyxlQUFlO1FBQzFCLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxpQkFBaUIsQ0FBQyxDQUFDO1FBQy9FLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUM5QixDQUFDO0lBRU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxVQUE0RyxFQUFFO1FBQy9ILElBQUksT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2xCLE9BQU8sQ0FBQyxHQUFHLENBQUMsNEJBQTRCLENB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
81
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5jYXJnb3J1bm5lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL21vZF9jYXJnby9jbGFzc2VzLmNhcmdvcnVubmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBUXpDLE1BQU0sT0FBTyxXQUFXO0lBQ2QsS0FBSyxDQUFnQztJQUNyQyxPQUFPLENBQVM7SUFDaEIsU0FBUyxDQUFTO0lBRTFCLFlBQVksT0FBZSxFQUFFLFlBQW9CLEVBQUU7UUFDakQsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7UUFDM0IsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDO1lBQzdDLFFBQVEsRUFBRSxNQUFNO1NBQ2pCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTSxLQUFLLENBQUMsbUJBQW1CO1FBQzlCLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxpQkFBaUIsQ0FBQyxDQUFDO1FBQy9FLE9BQU8sTUFBTSxDQUFDLFFBQVEsS0FBSyxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUVNLEtBQUssQ0FBQyxlQUFlO1FBQzFCLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxpQkFBaUIsQ0FBQyxDQUFDO1FBQy9FLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUM5QixDQUFDO0lBRU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxVQUFnSSxFQUFFO1FBQ25KLElBQUksT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2xCLE9BQU8sQ0FBQyxHQUFHLENBQUMsNEJBQTRCLENB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
@@ -0,0 +1,37 @@
1
+ export declare const toolCacheMarkerFile = ".gitzone-tool-cache.json";
2
+ export declare const tsrustCacheOwner = "@git.zone/tsrust";
3
+ export declare const targetCacheKind = "rust-target-cache";
4
+ export interface IToolCacheMarker {
5
+ owner: string;
6
+ kind: string;
7
+ safeToPrune: boolean;
8
+ createdAt: string;
9
+ schemaVersion: 1;
10
+ }
11
+ export interface ITsrustPruneCandidate {
12
+ path: string;
13
+ workspace: string;
14
+ bytes: number;
15
+ marked: boolean;
16
+ shouldPrune: boolean;
17
+ reason: string;
18
+ truncated?: boolean;
19
+ }
20
+ export interface ITsrustPruneOptions {
21
+ workspace: string;
22
+ targetDir?: string;
23
+ days?: number;
24
+ maxSizeBytes?: number;
25
+ }
26
+ export declare function createTargetCacheMarker(): IToolCacheMarker;
27
+ export declare function isValidTargetCacheMarker(markerArg: unknown): markerArg is IToolCacheMarker;
28
+ export declare function getDefaultManagedTargetDir(workspaceArg: string): string;
29
+ export declare function isSafeManagedTargetDir(workspaceArg: string, targetDirArg: string): boolean;
30
+ export declare function resolveManagedTargetDir(workspaceArg: string, configTargetDirArg?: string): string;
31
+ export declare function getCargoArtifactDir(targetDirArg: string, profileArg: string, targetTripleArg?: string): string;
32
+ export declare function parseSizeToBytes(valueArg: string | undefined): number | undefined;
33
+ export declare function writeTargetCacheMarker(targetDirArg: string): Promise<void>;
34
+ export declare function readTargetCacheMarker(targetDirArg: string): Promise<IToolCacheMarker | undefined>;
35
+ export declare function getDirectorySize(pathArg: string): Promise<number>;
36
+ export declare function createTsrustPrunePlan(optionsArg: ITsrustPruneOptions): Promise<ITsrustPruneCandidate[]>;
37
+ export declare function applyTsrustPrunePlan(planArg: ITsrustPruneCandidate[]): Promise<void>;
@@ -0,0 +1,260 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ export const toolCacheMarkerFile = '.gitzone-tool-cache.json';
4
+ export const tsrustCacheOwner = '@git.zone/tsrust';
5
+ export const targetCacheKind = 'rust-target-cache';
6
+ export function createTargetCacheMarker() {
7
+ return {
8
+ owner: tsrustCacheOwner,
9
+ kind: targetCacheKind,
10
+ safeToPrune: true,
11
+ createdAt: new Date().toISOString(),
12
+ schemaVersion: 1,
13
+ };
14
+ }
15
+ export function isValidTargetCacheMarker(markerArg) {
16
+ const marker = markerArg;
17
+ return marker.owner === tsrustCacheOwner
18
+ && marker.kind === targetCacheKind
19
+ && marker.safeToPrune === true
20
+ && marker.schemaVersion === 1;
21
+ }
22
+ export function getDefaultManagedTargetDir(workspaceArg) {
23
+ return path.resolve(workspaceArg, '.nogit', 'tsrust-target');
24
+ }
25
+ export function isSafeManagedTargetDir(workspaceArg, targetDirArg) {
26
+ const workspace = path.resolve(workspaceArg);
27
+ const targetDir = path.resolve(targetDirArg);
28
+ const relative = path.relative(workspace, targetDir);
29
+ if (!relative || relative.startsWith('..') || path.isAbsolute(relative)) {
30
+ return false;
31
+ }
32
+ return relative === path.join('.nogit', 'tsrust-target')
33
+ || relative.startsWith(`${path.join('.nogit', 'tsrust-')}`)
34
+ || relative.startsWith(`${path.join('.nogit', 'tsrust')}${path.sep}`);
35
+ }
36
+ export function resolveManagedTargetDir(workspaceArg, configTargetDirArg) {
37
+ const configured = process.env.TSRUST_TARGET_DIR || configTargetDirArg;
38
+ const targetDir = configured
39
+ ? path.isAbsolute(configured) ? configured : path.resolve(workspaceArg, configured)
40
+ : getDefaultManagedTargetDir(workspaceArg);
41
+ if (!isSafeManagedTargetDir(workspaceArg, targetDir)) {
42
+ throw new Error(`Refusing unsafe tsrust target dir outside workspace .nogit/: ${targetDir}`);
43
+ }
44
+ return targetDir;
45
+ }
46
+ export function getCargoArtifactDir(targetDirArg, profileArg, targetTripleArg) {
47
+ return targetTripleArg
48
+ ? path.join(targetDirArg, targetTripleArg, profileArg)
49
+ : path.join(targetDirArg, profileArg);
50
+ }
51
+ export function parseSizeToBytes(valueArg) {
52
+ if (!valueArg) {
53
+ return undefined;
54
+ }
55
+ const match = valueArg.trim().match(/^(\d+(?:\.\d+)?)(b|kb|kib|mb|mib|gb|gib)?$/i);
56
+ if (!match) {
57
+ return undefined;
58
+ }
59
+ const value = Number(match[1]);
60
+ const unit = (match[2] || 'b').toLowerCase();
61
+ const multiplier = unit === 'gb' || unit === 'gib'
62
+ ? 1024 ** 3
63
+ : unit === 'mb' || unit === 'mib'
64
+ ? 1024 ** 2
65
+ : unit === 'kb' || unit === 'kib'
66
+ ? 1024
67
+ : 1;
68
+ return Math.round(value * multiplier);
69
+ }
70
+ export async function writeTargetCacheMarker(targetDirArg) {
71
+ await fs.mkdir(targetDirArg, { recursive: true });
72
+ const existingMarker = await readTargetCacheMarker(targetDirArg);
73
+ if (existingMarker) {
74
+ return;
75
+ }
76
+ const entries = await fs.readdir(targetDirArg);
77
+ if (entries.length > 0) {
78
+ throw new Error(`Refusing to mark pre-existing non-empty tsrust target cache: ${targetDirArg}`);
79
+ }
80
+ await fs.writeFile(path.join(targetDirArg, toolCacheMarkerFile), `${JSON.stringify(createTargetCacheMarker(), null, 2)}\n`);
81
+ }
82
+ export async function readTargetCacheMarker(targetDirArg) {
83
+ try {
84
+ const markerRaw = await fs.readFile(path.join(targetDirArg, toolCacheMarkerFile), 'utf8');
85
+ const marker = JSON.parse(markerRaw);
86
+ return isValidTargetCacheMarker(marker) ? marker : undefined;
87
+ }
88
+ catch {
89
+ return undefined;
90
+ }
91
+ }
92
+ async function pathExists(pathArg) {
93
+ try {
94
+ await fs.stat(pathArg);
95
+ return true;
96
+ }
97
+ catch {
98
+ return false;
99
+ }
100
+ }
101
+ export async function getDirectorySize(pathArg) {
102
+ let total = 0;
103
+ let entries;
104
+ try {
105
+ entries = await fs.readdir(pathArg, { withFileTypes: true });
106
+ }
107
+ catch {
108
+ return 0;
109
+ }
110
+ for (const entry of entries) {
111
+ const entryPath = path.join(pathArg, entry.name);
112
+ if (entry.isDirectory()) {
113
+ total += await getDirectorySize(entryPath);
114
+ }
115
+ else if (entry.isFile()) {
116
+ try {
117
+ total += (await fs.stat(entryPath)).size;
118
+ }
119
+ catch {
120
+ // Ignore files that disappear while planning a prune.
121
+ }
122
+ }
123
+ }
124
+ return total;
125
+ }
126
+ async function getDirectoryUsage(pathArg, maxEntriesArg = 100_000) {
127
+ let bytes = 0;
128
+ let newestMtimeMs = 0;
129
+ let visitedEntries = 0;
130
+ let truncated = false;
131
+ const visit = async (entryPathArg) => {
132
+ if (visitedEntries >= maxEntriesArg) {
133
+ truncated = true;
134
+ return;
135
+ }
136
+ visitedEntries++;
137
+ let stat;
138
+ try {
139
+ stat = await fs.stat(entryPathArg);
140
+ }
141
+ catch {
142
+ return;
143
+ }
144
+ newestMtimeMs = Math.max(newestMtimeMs, stat.mtimeMs);
145
+ if (stat.isFile()) {
146
+ bytes += stat.size;
147
+ return;
148
+ }
149
+ if (!stat.isDirectory()) {
150
+ return;
151
+ }
152
+ let entries;
153
+ try {
154
+ entries = await fs.readdir(entryPathArg, { withFileTypes: true });
155
+ }
156
+ catch {
157
+ return;
158
+ }
159
+ for (const entry of entries) {
160
+ if (visitedEntries >= maxEntriesArg) {
161
+ truncated = true;
162
+ return;
163
+ }
164
+ await visit(path.join(entryPathArg, entry.name));
165
+ }
166
+ };
167
+ await visit(pathArg);
168
+ return { bytes, newestMtimeMs, truncated };
169
+ }
170
+ async function getNewestMtimeMs(pathArg) {
171
+ let newest = 0;
172
+ try {
173
+ const stat = await fs.stat(pathArg);
174
+ newest = stat.mtimeMs;
175
+ }
176
+ catch {
177
+ return 0;
178
+ }
179
+ let entries;
180
+ try {
181
+ entries = await fs.readdir(pathArg, { withFileTypes: true });
182
+ }
183
+ catch {
184
+ return newest;
185
+ }
186
+ for (const entry of entries) {
187
+ const entryPath = path.join(pathArg, entry.name);
188
+ if (entry.isDirectory()) {
189
+ newest = Math.max(newest, await getNewestMtimeMs(entryPath));
190
+ }
191
+ else if (entry.isFile()) {
192
+ try {
193
+ newest = Math.max(newest, (await fs.stat(entryPath)).mtimeMs);
194
+ }
195
+ catch {
196
+ // Ignore files that disappear while planning a prune.
197
+ }
198
+ }
199
+ }
200
+ return newest;
201
+ }
202
+ export async function createTsrustPrunePlan(optionsArg) {
203
+ const workspace = path.resolve(optionsArg.workspace);
204
+ const managedTargetDir = optionsArg.targetDir
205
+ ? resolveManagedTargetDir(workspace, optionsArg.targetDir)
206
+ : resolveManagedTargetDir(workspace);
207
+ const candidates = [
208
+ managedTargetDir,
209
+ path.join(workspace, 'rust', 'target'),
210
+ path.join(workspace, 'ts_rust', 'target'),
211
+ ];
212
+ const uniqueCandidates = [...new Set(candidates.map((candidate) => path.resolve(candidate)))];
213
+ const pruneCandidates = [];
214
+ const maxAgeMs = typeof optionsArg.days === 'number' ? optionsArg.days * 24 * 60 * 60 * 1000 : undefined;
215
+ for (const candidate of uniqueCandidates) {
216
+ if (!(await pathExists(candidate))) {
217
+ continue;
218
+ }
219
+ const marker = await readTargetCacheMarker(candidate);
220
+ const usage = await getDirectoryUsage(candidate);
221
+ const isManagedTarget = isSafeManagedTargetDir(workspace, candidate);
222
+ const ageMatches = typeof maxAgeMs === 'number' ? Date.now() - usage.newestMtimeMs >= maxAgeMs : false;
223
+ const bytes = usage.bytes;
224
+ const sizeMatches = typeof optionsArg.maxSizeBytes === 'number' ? bytes >= optionsArg.maxSizeBytes : false;
225
+ const shouldPrune = !!marker && isManagedTarget && (ageMatches || sizeMatches);
226
+ const reason = marker
227
+ ? !isManagedTarget
228
+ ? 'marked Rust target outside managed tsrust target allowlist; report-only'
229
+ : shouldPrune
230
+ ? [ageMatches ? `older than ${optionsArg.days} day(s)` : '', sizeMatches ? `at least ${optionsArg.maxSizeBytes} bytes` : ''].filter(Boolean).join(', ')
231
+ : 'marked tsrust target cache; below prune thresholds'
232
+ : 'unmarked conventional Rust target; report-only';
233
+ pruneCandidates.push({
234
+ path: candidate,
235
+ workspace,
236
+ bytes,
237
+ marked: !!marker,
238
+ shouldPrune,
239
+ reason,
240
+ truncated: usage.truncated,
241
+ });
242
+ }
243
+ return pruneCandidates;
244
+ }
245
+ export async function applyTsrustPrunePlan(planArg) {
246
+ for (const candidate of planArg) {
247
+ if (!candidate.shouldPrune) {
248
+ continue;
249
+ }
250
+ if (!isSafeManagedTargetDir(candidate.workspace, candidate.path)) {
251
+ throw new Error(`Refusing unsafe Rust target cache path: ${candidate.path}`);
252
+ }
253
+ const marker = await readTargetCacheMarker(candidate.path);
254
+ if (!marker) {
255
+ throw new Error(`Refusing to remove unmarked Rust target cache: ${candidate.path}`);
256
+ }
257
+ await fs.rm(candidate.path, { recursive: true, force: true });
258
+ }
259
+ }
260
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy50YXJnZXRjYWNoZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL21vZF9jYXJnby9jbGFzc2VzLnRhcmdldGNhY2hlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDdkMsT0FBTyxLQUFLLElBQUksTUFBTSxXQUFXLENBQUM7QUFFbEMsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUcsMEJBQTBCLENBQUM7QUFDOUQsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQUcsa0JBQWtCLENBQUM7QUFDbkQsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHLG1CQUFtQixDQUFDO0FBMkJuRCxNQUFNLFVBQVUsdUJBQXVCO0lBQ3JDLE9BQU87UUFDTCxLQUFLLEVBQUUsZ0JBQWdCO1FBQ3ZCLElBQUksRUFBRSxlQUFlO1FBQ3JCLFdBQVcsRUFBRSxJQUFJO1FBQ2pCLFNBQVMsRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRTtRQUNuQyxhQUFhLEVBQUUsQ0FBQztLQUNqQixDQUFDO0FBQ0osQ0FBQztBQUVELE1BQU0sVUFBVSx3QkFBd0IsQ0FBQyxTQUFrQjtJQUN6RCxNQUFNLE1BQU0sR0FBRyxTQUFzQyxDQUFDO0lBQ3RELE9BQU8sTUFBTSxDQUFDLEtBQUssS0FBSyxnQkFBZ0I7V0FDbkMsTUFBTSxDQUFDLElBQUksS0FBSyxlQUFlO1dBQy9CLE1BQU0sQ0FBQyxXQUFXLEtBQUssSUFBSTtXQUMzQixNQUFNLENBQUMsYUFBYSxLQUFLLENBQUMsQ0FBQztBQUNsQyxDQUFDO0FBRUQsTUFBTSxVQUFVLDBCQUEwQixDQUFDLFlBQW9CO0lBQzdELE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLEVBQUUsUUFBUSxFQUFFLGVBQWUsQ0FBQyxDQUFDO0FBQy9ELENBQUM7QUFFRCxNQUFNLFVBQVUsc0JBQXNCLENBQUMsWUFBb0IsRUFBRSxZQUFvQjtJ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
@@ -1,2 +1,3 @@
1
1
  export { CargoConfig } from './classes.cargoconfig.js';
2
2
  export { CargoRunner } from './classes.cargorunner.js';
3
+ export * from './classes.targetcache.js';
@@ -1,3 +1,4 @@
1
1
  export { CargoConfig } from './classes.cargoconfig.js';
2
2
  export { CargoRunner } from './classes.cargorunner.js';
3
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9tb2RfY2FyZ28vaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQyJ9
3
+ export * from './classes.targetcache.js';
4
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9tb2RfY2FyZ28vaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN2RCxjQUFjLDBCQUEwQixDQUFDIn0=
@@ -11,8 +11,10 @@ export declare class TsRustCli {
11
11
  */
12
12
  private resolveToolchain;
13
13
  private registerStandardCommand;
14
+ private shouldPruneAfterBuild;
14
15
  private buildRustflags;
15
16
  private registerCleanCommand;
17
+ private registerPruneCommand;
16
18
  private detectRustDir;
17
19
  run(): void;
18
20
  }
@@ -3,6 +3,7 @@ import * as os from 'os';
3
3
  import * as plugins from '../plugins.js';
4
4
  import { CargoConfig } from '../mod_cargo/index.js';
5
5
  import { CargoRunner } from '../mod_cargo/index.js';
6
+ import { applyTsrustPrunePlan, createTsrustPrunePlan, getCargoArtifactDir, parseSizeToBytes, resolveManagedTargetDir, writeTargetCacheMarker, } from '../mod_cargo/index.js';
6
7
  import { ElfInspector } from '../mod_elf/index.js';
7
8
  import { FsHelpers } from '../mod_fs/index.js';
8
9
  import { ToolchainManager } from '../mod_toolchain/index.js';
@@ -59,6 +60,7 @@ export class TsRustCli {
59
60
  registerCommands() {
60
61
  this.registerStandardCommand();
61
62
  this.registerCleanCommand();
63
+ this.registerPruneCommand();
62
64
  }
63
65
  /**
64
66
  * Resolves the Rust toolchain to use. Tries system cargo first,
@@ -107,6 +109,8 @@ export class TsRustCli {
107
109
  const shouldClean = !!argvArg.clean;
108
110
  const distDir = path.join(this.cwd, 'dist_rust');
109
111
  const profile = isDebug ? 'debug' : 'release';
112
+ const managedTargetDir = resolveManagedTargetDir(this.cwd, this.config.targetDir);
113
+ await writeTargetCacheMarker(managedTargetDir);
110
114
  // Parse --target flag (can appear multiple times), fall back to smartconfig.json config
111
115
  const cliTargets = argvArg.target;
112
116
  const targets = cliTargets
@@ -140,13 +144,13 @@ export class TsRustCli {
140
144
  target: triple,
141
145
  crtStatic: useStatic && wantsCrtStatic(triple),
142
146
  rustflags,
147
+ targetDir: managedTargetDir,
143
148
  });
144
149
  if (!buildResult.success) {
145
150
  console.error(`Build failed for target ${triple} with exit code ${buildResult.exitCode}`);
146
151
  process.exit(1);
147
152
  }
148
- // Cross-compiled binaries go to target/<triple>/<profile>/
149
- const targetDir = path.join(rustDir, 'target', triple, profile);
153
+ const targetDir = getCargoArtifactDir(managedTargetDir, profile, triple);
150
154
  for (const binName of workspaceInfo.binTargets) {
151
155
  const srcBinary = path.join(targetDir, binName);
152
156
  const destName = `${binName}_${friendly}`;
@@ -191,14 +195,13 @@ export class TsRustCli {
191
195
  target: nativeTriple,
192
196
  crtStatic: !!nativeTriple && wantsCrtStatic(nativeTriple),
193
197
  rustflags,
198
+ targetDir: managedTargetDir,
194
199
  });
195
200
  if (!buildResult.success) {
196
201
  console.error(`Build failed with exit code ${buildResult.exitCode}`);
197
202
  process.exit(1);
198
203
  }
199
- const targetDir = nativeTriple
200
- ? path.join(rustDir, 'target', nativeTriple, profile)
201
- : path.join(rustDir, 'target', profile);
204
+ const targetDir = getCargoArtifactDir(managedTargetDir, profile, nativeTriple);
202
205
  await FsHelpers.ensureEmptyDir(distDir);
203
206
  for (const binName of workspaceInfo.binTargets) {
204
207
  const srcBinary = path.join(targetDir, binName);
@@ -220,10 +223,23 @@ export class TsRustCli {
220
223
  }
221
224
  }
222
225
  }
226
+ if (this.shouldPruneAfterBuild()) {
227
+ const plan = await createTsrustPrunePlan({
228
+ workspace: this.cwd,
229
+ targetDir: managedTargetDir,
230
+ days: 0,
231
+ });
232
+ await applyTsrustPrunePlan(plan);
233
+ console.log('Pruned marked tsrust target cache after successful build.');
234
+ }
223
235
  const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
224
236
  console.log(`\nDone in ${elapsed}s`);
225
237
  });
226
238
  }
239
+ shouldPruneAfterBuild() {
240
+ const normalized = process.env.TSRUST_PRUNE_AFTER_BUILD?.toLowerCase();
241
+ return normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'y' || this.config.pruneAfterBuild === true;
242
+ }
227
243
  buildRustflags(rustDir) {
228
244
  const rustflags = [...(this.config.rustflags || [])];
229
245
  if (this.config.remapLocalPaths) {
@@ -248,7 +264,7 @@ export class TsRustCli {
248
264
  const envPrefix = await this.resolveToolchain();
249
265
  console.log('Running cargo clean...');
250
266
  const runner = new CargoRunner(rustDir, envPrefix);
251
- await runner.clean();
267
+ await runner.clean({ targetDir: resolveManagedTargetDir(this.cwd, this.config.targetDir) });
252
268
  console.log('Cargo clean complete.');
253
269
  }
254
270
  // Remove dist_rust/
@@ -260,6 +276,35 @@ export class TsRustCli {
260
276
  console.log('Clean complete.');
261
277
  });
262
278
  }
279
+ registerPruneCommand() {
280
+ this.cli.addCommand('prune').subscribe(async (argvArg) => {
281
+ const workspace = argvArg.workspace || this.cwd;
282
+ const daysArg = argvArg.days;
283
+ const days = daysArg === undefined ? 14 : Number(daysArg);
284
+ const maxSizeBytes = parseSizeToBytes(argvArg.maxSize);
285
+ const apply = !!argvArg.apply;
286
+ const plan = await createTsrustPrunePlan({
287
+ workspace,
288
+ targetDir: resolveManagedTargetDir(workspace, this.config.targetDir),
289
+ days: Number.isFinite(days) ? days : 14,
290
+ maxSizeBytes,
291
+ });
292
+ console.log(apply ? 'tsrust prune apply plan:' : 'tsrust prune dry-run plan:');
293
+ if (plan.length === 0) {
294
+ console.log('No Rust target caches found.');
295
+ }
296
+ for (const candidate of plan) {
297
+ const action = candidate.shouldPrune ? (apply ? 'remove' : 'would remove') : 'report';
298
+ console.log(`${action}: ${candidate.path} (${FsHelpers.formatFileSize(candidate.bytes)}) - ${candidate.reason}`);
299
+ }
300
+ if (apply) {
301
+ await applyTsrustPrunePlan(plan);
302
+ }
303
+ else {
304
+ console.log('Dry-run only. Re-run with --apply to remove marked tsrust target caches.');
305
+ }
306
+ });
307
+ }
263
308
  async detectRustDir() {
264
309
  // Check rust/ first
265
310
  const rustDir = path.join(this.cwd, 'rust');
@@ -281,4 +326,4 @@ export const runCli = async () => {
281
326
  const cli = new TsRustCli();
282
327
  cli.run();
283
328
  };
284
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy50c3J1c3RjbGkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9tb2RfY2xpL2NsYXNzZXMudHNydXN0Y2xpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sS0FBSyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3pCLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDcEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUMvQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUU3RCx3REFBd0Q7QUFDeEQsTUFBTSxjQUFjLEdBQTJCO0lBQzdDLFdBQVcsRUFBRSwwQkFBMEI7SUFDdkMsV0FBVyxFQUFFLDJCQUEyQjtJQUN4QyxnQkFBZ0IsRUFBRSwyQkFBMkI7SUFDN0MsZ0JBQWdCLEVBQUUsNEJBQTRCO0lBQzlDLFdBQVcsRUFBRSxxQkFBcUI7SUFDbEMsV0FBVyxFQUFFLHNCQUFzQjtDQUNwQyxDQUFDO0FBRUYsK0NBQStDO0FBQy9DLE1BQU0sbUJBQW1CLEdBQTJCLEVBQUUsQ0FBQztBQUN2RCxLQUFLLE1BQU0sQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDO0lBQ2hFLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxHQUFHLFFBQVEsQ0FBQztBQUN6QyxDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsU0FBUyxrQkFBa0IsQ0FBQyxJQUFZO0lBQ3RDLE9BQU8sY0FBYyxDQUFDLElBQUksQ0FB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
329
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy50c3J1c3RjbGkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9tb2RfY2xpL2NsYXNzZXMudHNydXN0Y2xpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sS0FBSyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3pCLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDcEQsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixxQkFBcUIsRUFDckIsbUJBQW1CLEVBQ25CLGdCQUFnQixFQUNoQix1QkFBdUIsRUFDdkIsc0JBQXNCLEdBQ3ZCLE1BQU0sdUJBQXVCLENBQUM7QUFDL0IsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUMvQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUU3RCx3REFBd0Q7QUFDeEQsTUFBTSxjQUFjLEdBQTJCO0lBQzdDLFdBQVcsRUFBRSwwQkFBMEI7SUFDdkMsV0FBVyxFQUFFLDJCQUEyQjtJQUN4QyxnQkFBZ0IsRUFBRSwyQkFBMkI7SUFDN0MsZ0JBQWdCLEVBQUUsNEJBQTRCO0lBQzlDLFdBQVcsRUFBRSxxQkFBcUI7SUFDbEMsV0FBVyxFQUFFLHNCQUFzQjtDQUNwQyxDQUFDO0FBRUYsK0NBQStDO0FBQy9DLE1BQU0sbUJBQW1CLEdBQTJCLEVBQUUsQ0FBQztBQUN2RCxLQUFLLE1BQU0sQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDO0lBQ2hFLG1CQUFt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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@git.zone/tsrust",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "private": false,
5
5
  "description": "A tool for compiling Rust projects, detecting Cargo workspaces, building with cargo, and placing binaries in a conventional dist_rust directory.",
6
6
  "main": "dist_ts/index.js",
@@ -41,7 +41,7 @@
41
41
  "@git.zone/tsbuild": "^4.4.2",
42
42
  "@git.zone/tsrun": "^2.0.4",
43
43
  "@git.zone/tstest": "^3.6.6",
44
- "@types/node": "^25.9.2"
44
+ "@types/node": "^25.9.3"
45
45
  },
46
46
  "files": [
47
47
  "ts/**/*",
package/readme.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @git.zone/tsrust
2
2
 
3
- A CLI build tool for Rust projects that follows the same conventions as `@git.zone/tsbuild`. It detects your `rust/` source directory, parses `Cargo.toml` (including workspaces), runs `cargo build --release`, and copies the resulting binaries into a clean `dist_rust/` directory at the project root.
3
+ A CLI build tool for Rust projects that follows the same conventions as `@git.zone/tsbuild`. It detects your `rust/` source directory, parses `Cargo.toml` (including workspaces), runs `cargo build --release` with a managed target cache, and copies the resulting binaries into a clean `dist_rust/` directory at the project root.
4
4
 
5
5
  ## Issue Reporting and Security
6
6
 
@@ -48,8 +48,9 @@ This will:
48
48
  2. Locate your `rust/` directory (containing `Cargo.toml`)
49
49
  3. Parse the workspace to discover all `[[bin]]` targets
50
50
  4. Run `cargo build --release` with full streaming output
51
- 5. Copy each binary to `dist_rust/` with executable permissions (`chmod 755`)
52
- 6. Report file sizes and total build time
51
+ 5. Store Cargo intermediates in `.nogit/tsrust-target` by default
52
+ 6. Copy each binary to `dist_rust/` with executable permissions (`chmod 755`)
53
+ 7. Report file sizes and total build time
53
54
 
54
55
  **Example output:**
55
56
 
@@ -58,7 +59,7 @@ Using cargo 1.90.0 (840b83a10 2025-07-30)
58
59
  Found Rust project at: rust
59
60
  Detected Cargo workspace
60
61
  Binary targets: rustproxy
61
- Running: cargo build --release
62
+ Running: CARGO_TARGET_DIR="/path/to/project/.nogit/tsrust-target" cargo build --release
62
63
  Compiling rustproxy v0.1.0
63
64
  Finished `release` profile [optimized] target(s) in 29.01s
64
65
  Copied rustproxy (13.4 MB) -> dist_rust/rustproxy
@@ -85,7 +86,7 @@ Build with the debug profile instead of release:
85
86
  tsrust --debug
86
87
  ```
87
88
 
88
- Binaries are taken from `rust/target/debug/` instead of `rust/target/release/`.
89
+ Binaries are taken from `.nogit/tsrust-target/debug/` instead of `.nogit/tsrust-target/release/`.
89
90
 
90
91
  ### 🧹 Clean Before Building
91
92
 
@@ -138,13 +139,17 @@ You can set default cross-compilation targets in your project's `.smartconfig.js
138
139
  ```json
139
140
  {
140
141
  "@git.zone/tsrust": {
141
- "targets": ["linux_arm64", "linux_amd64"]
142
+ "targets": ["linux_arm64", "linux_amd64"],
143
+ "targetDir": ".nogit/tsrust-target",
144
+ "pruneAfterBuild": false
142
145
  }
143
146
  }
144
147
  ```
145
148
 
146
149
  When targets are configured in `.smartconfig.json`, simply running `tsrust` will cross-compile for all listed targets. CLI `--target` flags take full precedence — if any `--target` is provided, the `.smartconfig.json` targets are ignored entirely.
147
150
 
151
+ `targetDir` is optional. It must point to a tsrust-owned path under `.nogit/`, such as `.nogit/tsrust-target` or `.nogit/tsrust-custom-target`. You can also set `TSRUST_TARGET_DIR` for one-off runs. `pruneAfterBuild: true` or `TSRUST_PRUNE_AFTER_BUILD=true` removes the marked managed target cache after binaries have been copied to `dist_rust/`.
152
+
148
153
  ### Static Linking
149
154
 
150
155
  `tsrust` can produce fully statically linked Linux binaries (static-pie) that run on both glibc distros (Debian/Ubuntu) and musl distros (Alpine). Enable it via `.smartconfig.json`:
@@ -211,6 +216,29 @@ tsrust clean
211
216
 
212
217
  This runs `cargo clean` in the Rust directory and deletes the `dist_rust/` output directory.
213
218
 
219
+ ### 🧹 Prune Rust Target Caches
220
+
221
+ Report Rust target caches without deleting anything:
222
+
223
+ ```bash
224
+ tsrust prune
225
+ ```
226
+
227
+ Apply cleanup to marked tsrust-managed target caches:
228
+
229
+ ```bash
230
+ tsrust prune --apply --days 14 --max-size 5GiB
231
+ ```
232
+
233
+ | Option | Description |
234
+ | --- | --- |
235
+ | `--apply` | Remove marked managed target caches that match the filters |
236
+ | `--days <n>` | Prune marked caches whose newest file is at least `n` days old; default `14` |
237
+ | `--max-size <size>` | Prune marked caches at or above a size such as `5GiB` |
238
+ | `--workspace <path>` | Inspect another workspace path |
239
+
240
+ Conventional `rust/target` and `ts_rust/target` directories are report-only, even if they carry a marker. Only managed `.nogit/tsrust*` target directories are eligible for `--apply`; arbitrary app data is never marked or removed.
241
+
214
242
  ## Project Structure
215
243
 
216
244
  `tsrust` expects your project to follow this layout:
@@ -230,6 +258,8 @@ my-project/
230
258
  │ └── src/
231
259
  ├── dist_rust/ # 📦 Output: compiled binaries go here
232
260
  │ └── my-binary
261
+ ├── .nogit/
262
+ │ └── tsrust-target/ # 🧹 Managed Cargo target cache
233
263
  ├── ts/ # (your TypeScript code, built by tsbuild)
234
264
  ├── dist_ts/ # (TypeScript output)
235
265
  └── package.json
@@ -253,7 +283,7 @@ If no `rust/` directory is found, `tsrust` checks for `ts_rust/` as a fallback.
253
283
  `tsrust` exports its internals for use in other Node.js/TypeScript tools:
254
284
 
255
285
  ```typescript
256
- import { CargoConfig, CargoRunner, FsHelpers, TsRustCli } from '@git.zone/tsrust';
286
+ import { CargoConfig, CargoRunner, FsHelpers, TsRustCli, resolveManagedTargetDir } from '@git.zone/tsrust';
257
287
 
258
288
  // Parse a Cargo workspace
259
289
  const config = new CargoConfig('/path/to/rust');
@@ -263,7 +293,8 @@ console.log(info.binTargets); // ['rustproxy']
263
293
 
264
294
  // Run cargo build
265
295
  const runner = new CargoRunner('/path/to/rust');
266
- const result = await runner.build({ debug: false, clean: false });
296
+ const targetDir = resolveManagedTargetDir('/path/to/project');
297
+ const result = await runner.build({ debug: false, clean: false, targetDir });
267
298
  console.log(result.success); // true
268
299
  console.log(result.exitCode); // 0
269
300
 
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@git.zone/tsrust',
6
- version: '1.5.0',
6
+ version: '1.6.0',
7
7
  description: 'A tool for compiling Rust projects, detecting Cargo workspaces, building with cargo, and placing binaries in a conventional dist_rust directory.'
8
8
  }
@@ -29,10 +29,10 @@ export class CargoRunner {
29
29
  return result.stdout.trim();
30
30
  }
31
31
 
32
- public async build(options: { debug?: boolean; clean?: boolean; target?: string; crtStatic?: boolean; rustflags?: string[] } = {}): Promise<ICargoRunResult> {
32
+ public async build(options: { debug?: boolean; clean?: boolean; target?: string; crtStatic?: boolean; rustflags?: string[]; targetDir?: string } = {}): Promise<ICargoRunResult> {
33
33
  if (options.clean) {
34
34
  console.log('Cleaning previous build...');
35
- await this.clean();
35
+ await this.clean({ targetDir: options.targetDir });
36
36
  }
37
37
 
38
38
  // crt-static may only be injected together with an explicit --target:
@@ -53,9 +53,10 @@ export class CargoRunner {
53
53
  rustflags.unshift('-C', 'target-feature=+crt-static');
54
54
  }
55
55
  const rustflagsPrefix = rustflags.length ? `RUSTFLAGS=${this.shellQuote(rustflags.join(' '))} ` : '';
56
- const command = `${this.envPrefix}cd ${this.rustDir} && ${rustflagsPrefix}cargo build${profile}${targetFlag}`;
56
+ const targetDirPrefix = options.targetDir ? `CARGO_TARGET_DIR=${this.shellQuote(options.targetDir)} ` : '';
57
+ const command = `${this.envPrefix}cd ${this.rustDir} && ${targetDirPrefix}${rustflagsPrefix}cargo build${profile}${targetFlag}`;
57
58
 
58
- console.log(`Running: ${rustflagsPrefix}cargo build${profile}${targetFlag}`);
59
+ console.log(`Running: ${targetDirPrefix}${rustflagsPrefix}cargo build${profile}${targetFlag}`);
59
60
  const result = await this.shell.exec(command);
60
61
 
61
62
  return {
@@ -85,8 +86,9 @@ export class CargoRunner {
85
86
  }
86
87
  }
87
88
 
88
- public async clean(): Promise<ICargoRunResult> {
89
- const command = `${this.envPrefix}cd ${this.rustDir} && cargo clean`;
89
+ public async clean(options: { targetDir?: string } = {}): Promise<ICargoRunResult> {
90
+ const targetDirPrefix = options.targetDir ? `CARGO_TARGET_DIR=${this.shellQuote(options.targetDir)} ` : '';
91
+ const command = `${this.envPrefix}cd ${this.rustDir} && ${targetDirPrefix}cargo clean`;
90
92
  const result = await this.shell.exec(command);
91
93
 
92
94
  return {
@@ -0,0 +1,304 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+
4
+ export const toolCacheMarkerFile = '.gitzone-tool-cache.json';
5
+ export const tsrustCacheOwner = '@git.zone/tsrust';
6
+ export const targetCacheKind = 'rust-target-cache';
7
+
8
+ export interface IToolCacheMarker {
9
+ owner: string;
10
+ kind: string;
11
+ safeToPrune: boolean;
12
+ createdAt: string;
13
+ schemaVersion: 1;
14
+ }
15
+
16
+ export interface ITsrustPruneCandidate {
17
+ path: string;
18
+ workspace: string;
19
+ bytes: number;
20
+ marked: boolean;
21
+ shouldPrune: boolean;
22
+ reason: string;
23
+ truncated?: boolean;
24
+ }
25
+
26
+ export interface ITsrustPruneOptions {
27
+ workspace: string;
28
+ targetDir?: string;
29
+ days?: number;
30
+ maxSizeBytes?: number;
31
+ }
32
+
33
+ export function createTargetCacheMarker(): IToolCacheMarker {
34
+ return {
35
+ owner: tsrustCacheOwner,
36
+ kind: targetCacheKind,
37
+ safeToPrune: true,
38
+ createdAt: new Date().toISOString(),
39
+ schemaVersion: 1,
40
+ };
41
+ }
42
+
43
+ export function isValidTargetCacheMarker(markerArg: unknown): markerArg is IToolCacheMarker {
44
+ const marker = markerArg as Partial<IToolCacheMarker>;
45
+ return marker.owner === tsrustCacheOwner
46
+ && marker.kind === targetCacheKind
47
+ && marker.safeToPrune === true
48
+ && marker.schemaVersion === 1;
49
+ }
50
+
51
+ export function getDefaultManagedTargetDir(workspaceArg: string): string {
52
+ return path.resolve(workspaceArg, '.nogit', 'tsrust-target');
53
+ }
54
+
55
+ export function isSafeManagedTargetDir(workspaceArg: string, targetDirArg: string): boolean {
56
+ const workspace = path.resolve(workspaceArg);
57
+ const targetDir = path.resolve(targetDirArg);
58
+ const relative = path.relative(workspace, targetDir);
59
+ if (!relative || relative.startsWith('..') || path.isAbsolute(relative)) {
60
+ return false;
61
+ }
62
+ return relative === path.join('.nogit', 'tsrust-target')
63
+ || relative.startsWith(`${path.join('.nogit', 'tsrust-')}`)
64
+ || relative.startsWith(`${path.join('.nogit', 'tsrust')}${path.sep}`);
65
+ }
66
+
67
+ export function resolveManagedTargetDir(workspaceArg: string, configTargetDirArg?: string): string {
68
+ const configured = process.env.TSRUST_TARGET_DIR || configTargetDirArg;
69
+ const targetDir = configured
70
+ ? path.isAbsolute(configured) ? configured : path.resolve(workspaceArg, configured)
71
+ : getDefaultManagedTargetDir(workspaceArg);
72
+ if (!isSafeManagedTargetDir(workspaceArg, targetDir)) {
73
+ throw new Error(`Refusing unsafe tsrust target dir outside workspace .nogit/: ${targetDir}`);
74
+ }
75
+ return targetDir;
76
+ }
77
+
78
+ export function getCargoArtifactDir(targetDirArg: string, profileArg: string, targetTripleArg?: string): string {
79
+ return targetTripleArg
80
+ ? path.join(targetDirArg, targetTripleArg, profileArg)
81
+ : path.join(targetDirArg, profileArg);
82
+ }
83
+
84
+ export function parseSizeToBytes(valueArg: string | undefined): number | undefined {
85
+ if (!valueArg) {
86
+ return undefined;
87
+ }
88
+ const match = valueArg.trim().match(/^(\d+(?:\.\d+)?)(b|kb|kib|mb|mib|gb|gib)?$/i);
89
+ if (!match) {
90
+ return undefined;
91
+ }
92
+ const value = Number(match[1]);
93
+ const unit = (match[2] || 'b').toLowerCase();
94
+ const multiplier = unit === 'gb' || unit === 'gib'
95
+ ? 1024 ** 3
96
+ : unit === 'mb' || unit === 'mib'
97
+ ? 1024 ** 2
98
+ : unit === 'kb' || unit === 'kib'
99
+ ? 1024
100
+ : 1;
101
+ return Math.round(value * multiplier);
102
+ }
103
+
104
+ export async function writeTargetCacheMarker(targetDirArg: string): Promise<void> {
105
+ await fs.mkdir(targetDirArg, { recursive: true });
106
+ const existingMarker = await readTargetCacheMarker(targetDirArg);
107
+ if (existingMarker) {
108
+ return;
109
+ }
110
+ const entries = await fs.readdir(targetDirArg);
111
+ if (entries.length > 0) {
112
+ throw new Error(`Refusing to mark pre-existing non-empty tsrust target cache: ${targetDirArg}`);
113
+ }
114
+ await fs.writeFile(
115
+ path.join(targetDirArg, toolCacheMarkerFile),
116
+ `${JSON.stringify(createTargetCacheMarker(), null, 2)}\n`,
117
+ );
118
+ }
119
+
120
+ export async function readTargetCacheMarker(targetDirArg: string): Promise<IToolCacheMarker | undefined> {
121
+ try {
122
+ const markerRaw = await fs.readFile(path.join(targetDirArg, toolCacheMarkerFile), 'utf8');
123
+ const marker = JSON.parse(markerRaw);
124
+ return isValidTargetCacheMarker(marker) ? marker : undefined;
125
+ } catch {
126
+ return undefined;
127
+ }
128
+ }
129
+
130
+ async function pathExists(pathArg: string): Promise<boolean> {
131
+ try {
132
+ await fs.stat(pathArg);
133
+ return true;
134
+ } catch {
135
+ return false;
136
+ }
137
+ }
138
+
139
+ export async function getDirectorySize(pathArg: string): Promise<number> {
140
+ let total = 0;
141
+ let entries;
142
+ try {
143
+ entries = await fs.readdir(pathArg, { withFileTypes: true });
144
+ } catch {
145
+ return 0;
146
+ }
147
+
148
+ for (const entry of entries) {
149
+ const entryPath = path.join(pathArg, entry.name);
150
+ if (entry.isDirectory()) {
151
+ total += await getDirectorySize(entryPath);
152
+ } else if (entry.isFile()) {
153
+ try {
154
+ total += (await fs.stat(entryPath)).size;
155
+ } catch {
156
+ // Ignore files that disappear while planning a prune.
157
+ }
158
+ }
159
+ }
160
+
161
+ return total;
162
+ }
163
+
164
+ async function getDirectoryUsage(pathArg: string, maxEntriesArg = 100_000): Promise<{ bytes: number; newestMtimeMs: number; truncated: boolean }> {
165
+ let bytes = 0;
166
+ let newestMtimeMs = 0;
167
+ let visitedEntries = 0;
168
+ let truncated = false;
169
+
170
+ const visit = async (entryPathArg: string): Promise<void> => {
171
+ if (visitedEntries >= maxEntriesArg) {
172
+ truncated = true;
173
+ return;
174
+ }
175
+ visitedEntries++;
176
+
177
+ let stat;
178
+ try {
179
+ stat = await fs.stat(entryPathArg);
180
+ } catch {
181
+ return;
182
+ }
183
+ newestMtimeMs = Math.max(newestMtimeMs, stat.mtimeMs);
184
+ if (stat.isFile()) {
185
+ bytes += stat.size;
186
+ return;
187
+ }
188
+ if (!stat.isDirectory()) {
189
+ return;
190
+ }
191
+
192
+ let entries;
193
+ try {
194
+ entries = await fs.readdir(entryPathArg, { withFileTypes: true });
195
+ } catch {
196
+ return;
197
+ }
198
+ for (const entry of entries) {
199
+ if (visitedEntries >= maxEntriesArg) {
200
+ truncated = true;
201
+ return;
202
+ }
203
+ await visit(path.join(entryPathArg, entry.name));
204
+ }
205
+ };
206
+
207
+ await visit(pathArg);
208
+ return { bytes, newestMtimeMs, truncated };
209
+ }
210
+
211
+ async function getNewestMtimeMs(pathArg: string): Promise<number> {
212
+ let newest = 0;
213
+ try {
214
+ const stat = await fs.stat(pathArg);
215
+ newest = stat.mtimeMs;
216
+ } catch {
217
+ return 0;
218
+ }
219
+
220
+ let entries;
221
+ try {
222
+ entries = await fs.readdir(pathArg, { withFileTypes: true });
223
+ } catch {
224
+ return newest;
225
+ }
226
+
227
+ for (const entry of entries) {
228
+ const entryPath = path.join(pathArg, entry.name);
229
+ if (entry.isDirectory()) {
230
+ newest = Math.max(newest, await getNewestMtimeMs(entryPath));
231
+ } else if (entry.isFile()) {
232
+ try {
233
+ newest = Math.max(newest, (await fs.stat(entryPath)).mtimeMs);
234
+ } catch {
235
+ // Ignore files that disappear while planning a prune.
236
+ }
237
+ }
238
+ }
239
+
240
+ return newest;
241
+ }
242
+
243
+ export async function createTsrustPrunePlan(optionsArg: ITsrustPruneOptions): Promise<ITsrustPruneCandidate[]> {
244
+ const workspace = path.resolve(optionsArg.workspace);
245
+ const managedTargetDir = optionsArg.targetDir
246
+ ? resolveManagedTargetDir(workspace, optionsArg.targetDir)
247
+ : resolveManagedTargetDir(workspace);
248
+ const candidates = [
249
+ managedTargetDir,
250
+ path.join(workspace, 'rust', 'target'),
251
+ path.join(workspace, 'ts_rust', 'target'),
252
+ ];
253
+ const uniqueCandidates = [...new Set(candidates.map((candidate) => path.resolve(candidate)))];
254
+ const pruneCandidates: ITsrustPruneCandidate[] = [];
255
+ const maxAgeMs = typeof optionsArg.days === 'number' ? optionsArg.days * 24 * 60 * 60 * 1000 : undefined;
256
+
257
+ for (const candidate of uniqueCandidates) {
258
+ if (!(await pathExists(candidate))) {
259
+ continue;
260
+ }
261
+ const marker = await readTargetCacheMarker(candidate);
262
+ const usage = await getDirectoryUsage(candidate);
263
+ const isManagedTarget = isSafeManagedTargetDir(workspace, candidate);
264
+ const ageMatches = typeof maxAgeMs === 'number' ? Date.now() - usage.newestMtimeMs >= maxAgeMs : false;
265
+ const bytes = usage.bytes;
266
+ const sizeMatches = typeof optionsArg.maxSizeBytes === 'number' ? bytes >= optionsArg.maxSizeBytes : false;
267
+ const shouldPrune = !!marker && isManagedTarget && (ageMatches || sizeMatches);
268
+ const reason = marker
269
+ ? !isManagedTarget
270
+ ? 'marked Rust target outside managed tsrust target allowlist; report-only'
271
+ : shouldPrune
272
+ ? [ageMatches ? `older than ${optionsArg.days} day(s)` : '', sizeMatches ? `at least ${optionsArg.maxSizeBytes} bytes` : ''].filter(Boolean).join(', ')
273
+ : 'marked tsrust target cache; below prune thresholds'
274
+ : 'unmarked conventional Rust target; report-only';
275
+
276
+ pruneCandidates.push({
277
+ path: candidate,
278
+ workspace,
279
+ bytes,
280
+ marked: !!marker,
281
+ shouldPrune,
282
+ reason,
283
+ truncated: usage.truncated,
284
+ });
285
+ }
286
+
287
+ return pruneCandidates;
288
+ }
289
+
290
+ export async function applyTsrustPrunePlan(planArg: ITsrustPruneCandidate[]): Promise<void> {
291
+ for (const candidate of planArg) {
292
+ if (!candidate.shouldPrune) {
293
+ continue;
294
+ }
295
+ if (!isSafeManagedTargetDir(candidate.workspace, candidate.path)) {
296
+ throw new Error(`Refusing unsafe Rust target cache path: ${candidate.path}`);
297
+ }
298
+ const marker = await readTargetCacheMarker(candidate.path);
299
+ if (!marker) {
300
+ throw new Error(`Refusing to remove unmarked Rust target cache: ${candidate.path}`);
301
+ }
302
+ await fs.rm(candidate.path, { recursive: true, force: true });
303
+ }
304
+ }
@@ -1,2 +1,3 @@
1
1
  export { CargoConfig } from './classes.cargoconfig.js';
2
2
  export { CargoRunner } from './classes.cargorunner.js';
3
+ export * from './classes.targetcache.js';
@@ -3,6 +3,14 @@ import * as os from 'os';
3
3
  import * as plugins from '../plugins.js';
4
4
  import { CargoConfig } from '../mod_cargo/index.js';
5
5
  import { CargoRunner } from '../mod_cargo/index.js';
6
+ import {
7
+ applyTsrustPrunePlan,
8
+ createTsrustPrunePlan,
9
+ getCargoArtifactDir,
10
+ parseSizeToBytes,
11
+ resolveManagedTargetDir,
12
+ writeTargetCacheMarker,
13
+ } from '../mod_cargo/index.js';
6
14
  import { ElfInspector } from '../mod_elf/index.js';
7
15
  import { FsHelpers } from '../mod_fs/index.js';
8
16
  import { ToolchainManager } from '../mod_toolchain/index.js';
@@ -48,6 +56,8 @@ interface ITsrustConfig {
48
56
  static?: boolean;
49
57
  rustflags?: string[];
50
58
  remapLocalPaths?: boolean;
59
+ targetDir?: string;
60
+ pruneAfterBuild?: boolean;
51
61
  }
52
62
 
53
63
  /** crt-static injection only applies to glibc targets; musl is static by default. */
@@ -75,6 +85,7 @@ export class TsRustCli {
75
85
  private registerCommands(): void {
76
86
  this.registerStandardCommand();
77
87
  this.registerCleanCommand();
88
+ this.registerPruneCommand();
78
89
  }
79
90
 
80
91
  /**
@@ -135,6 +146,8 @@ export class TsRustCli {
135
146
  const shouldClean = !!(argvArg as any).clean;
136
147
  const distDir = path.join(this.cwd, 'dist_rust');
137
148
  const profile = isDebug ? 'debug' : 'release';
149
+ const managedTargetDir = resolveManagedTargetDir(this.cwd, this.config.targetDir);
150
+ await writeTargetCacheMarker(managedTargetDir);
138
151
 
139
152
  // Parse --target flag (can appear multiple times), fall back to smartconfig.json config
140
153
  const cliTargets = (argvArg as any).target;
@@ -175,6 +188,7 @@ export class TsRustCli {
175
188
  target: triple,
176
189
  crtStatic: useStatic && wantsCrtStatic(triple),
177
190
  rustflags,
191
+ targetDir: managedTargetDir,
178
192
  });
179
193
 
180
194
  if (!buildResult.success) {
@@ -182,8 +196,7 @@ export class TsRustCli {
182
196
  process.exit(1);
183
197
  }
184
198
 
185
- // Cross-compiled binaries go to target/<triple>/<profile>/
186
- const targetDir = path.join(rustDir, 'target', triple, profile);
199
+ const targetDir = getCargoArtifactDir(managedTargetDir, profile, triple);
187
200
 
188
201
  for (const binName of workspaceInfo.binTargets) {
189
202
  const srcBinary = path.join(targetDir, binName);
@@ -234,6 +247,7 @@ export class TsRustCli {
234
247
  target: nativeTriple,
235
248
  crtStatic: !!nativeTriple && wantsCrtStatic(nativeTriple),
236
249
  rustflags,
250
+ targetDir: managedTargetDir,
237
251
  });
238
252
 
239
253
  if (!buildResult.success) {
@@ -241,9 +255,7 @@ export class TsRustCli {
241
255
  process.exit(1);
242
256
  }
243
257
 
244
- const targetDir = nativeTriple
245
- ? path.join(rustDir, 'target', nativeTriple, profile)
246
- : path.join(rustDir, 'target', profile);
258
+ const targetDir = getCargoArtifactDir(managedTargetDir, profile, nativeTriple);
247
259
 
248
260
  await FsHelpers.ensureEmptyDir(distDir);
249
261
 
@@ -272,11 +284,26 @@ export class TsRustCli {
272
284
  }
273
285
  }
274
286
 
287
+ if (this.shouldPruneAfterBuild()) {
288
+ const plan = await createTsrustPrunePlan({
289
+ workspace: this.cwd,
290
+ targetDir: managedTargetDir,
291
+ days: 0,
292
+ });
293
+ await applyTsrustPrunePlan(plan);
294
+ console.log('Pruned marked tsrust target cache after successful build.');
295
+ }
296
+
275
297
  const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
276
298
  console.log(`\nDone in ${elapsed}s`);
277
299
  });
278
300
  }
279
301
 
302
+ private shouldPruneAfterBuild(): boolean {
303
+ const normalized = process.env.TSRUST_PRUNE_AFTER_BUILD?.toLowerCase();
304
+ return normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'y' || this.config.pruneAfterBuild === true;
305
+ }
306
+
280
307
  private buildRustflags(rustDir: string): string[] {
281
308
  const rustflags = [...(this.config.rustflags || [])];
282
309
  if (this.config.remapLocalPaths) {
@@ -303,7 +330,7 @@ export class TsRustCli {
303
330
  const envPrefix = await this.resolveToolchain();
304
331
  console.log('Running cargo clean...');
305
332
  const runner = new CargoRunner(rustDir, envPrefix);
306
- await runner.clean();
333
+ await runner.clean({ targetDir: resolveManagedTargetDir(this.cwd, this.config.targetDir) });
307
334
  console.log('Cargo clean complete.');
308
335
  }
309
336
 
@@ -318,6 +345,36 @@ export class TsRustCli {
318
345
  });
319
346
  }
320
347
 
348
+ private registerPruneCommand(): void {
349
+ this.cli.addCommand('prune').subscribe(async (argvArg) => {
350
+ const workspace = ((argvArg as any).workspace as string | undefined) || this.cwd;
351
+ const daysArg = (argvArg as any).days;
352
+ const days = daysArg === undefined ? 14 : Number(daysArg);
353
+ const maxSizeBytes = parseSizeToBytes((argvArg as any).maxSize as string | undefined);
354
+ const apply = !!(argvArg as any).apply;
355
+ const plan = await createTsrustPrunePlan({
356
+ workspace,
357
+ targetDir: resolveManagedTargetDir(workspace, this.config.targetDir),
358
+ days: Number.isFinite(days) ? days : 14,
359
+ maxSizeBytes,
360
+ });
361
+
362
+ console.log(apply ? 'tsrust prune apply plan:' : 'tsrust prune dry-run plan:');
363
+ if (plan.length === 0) {
364
+ console.log('No Rust target caches found.');
365
+ }
366
+ for (const candidate of plan) {
367
+ const action = candidate.shouldPrune ? (apply ? 'remove' : 'would remove') : 'report';
368
+ console.log(`${action}: ${candidate.path} (${FsHelpers.formatFileSize(candidate.bytes)}) - ${candidate.reason}`);
369
+ }
370
+ if (apply) {
371
+ await applyTsrustPrunePlan(plan);
372
+ } else {
373
+ console.log('Dry-run only. Re-run with --apply to remove marked tsrust target caches.');
374
+ }
375
+ });
376
+ }
377
+
321
378
  private async detectRustDir(): Promise<string | null> {
322
379
  // Check rust/ first
323
380
  const rustDir = path.join(this.cwd, 'rust');