dex-termux-cli 0.2.3 → 0.3.0-beta.2
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/README.md +58 -61
- package/data/commands/explain.json +63 -0
- package/package.json +9 -3
- package/src/app/main.js +11 -1
- package/src/commands/android-shell.js +220 -27
- package/src/commands/context.js +22 -0
- package/src/commands/explain.js +11 -2
- package/src/commands/install.js +279 -28
- package/src/commands/menu.js +38 -5
- package/src/commands/safe-shell.js +211 -10
- package/src/commands/search.js +5 -1
- package/src/commands/tree.js +5 -1
- package/src/commands/version.js +84 -11
- package/src/core/args.js +13 -3
- package/src/core/config.js +43 -4
- package/src/core/scopes.js +22 -12
- package/src/ui/output.js +10 -7
- package/src/ui/prompt.js +77 -14
- package/src/utils/platform.js +116 -0
- package/src/utils/project-context.js +183 -31
- package/src/utils/shell.js +33 -7
package/src/commands/install.js
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from '../core/config.js';
|
|
11
11
|
import { printSection } from '../ui/output.js';
|
|
12
12
|
import { detectProjectContext } from '../utils/project-context.js';
|
|
13
|
+
import { isAndroidStoragePath, resolvePlatformMode, shouldRestrictProjectToAndroidStorage } from '../utils/platform.js';
|
|
13
14
|
|
|
14
15
|
const RUNTIME_CANDIDATES = {
|
|
15
16
|
python: [
|
|
@@ -23,6 +24,7 @@ const RUNTIME_CANDIDATES = {
|
|
|
23
24
|
ruby: ['ruby', '/data/data/com.termux/files/usr/bin/ruby'],
|
|
24
25
|
go: ['go', '/data/data/com.termux/files/usr/bin/go'],
|
|
25
26
|
rust: ['rustc', '/data/data/com.termux/files/usr/bin/rustc'],
|
|
27
|
+
java: ['java', '/data/data/com.termux/files/usr/bin/java'],
|
|
26
28
|
};
|
|
27
29
|
|
|
28
30
|
const RUNTIME_PACKAGES = {
|
|
@@ -32,6 +34,7 @@ const RUNTIME_PACKAGES = {
|
|
|
32
34
|
ruby: ['ruby'],
|
|
33
35
|
go: ['golang'],
|
|
34
36
|
rust: ['rust'],
|
|
37
|
+
java: [],
|
|
35
38
|
};
|
|
36
39
|
|
|
37
40
|
const RUNTIME_SMOKE_TESTS = {
|
|
@@ -41,20 +44,31 @@ const RUNTIME_SMOKE_TESTS = {
|
|
|
41
44
|
ruby: ['-e', 'puts "dex-ok"'],
|
|
42
45
|
go: ['version'],
|
|
43
46
|
rust: ['--version'],
|
|
47
|
+
java: ['--version'],
|
|
44
48
|
};
|
|
45
49
|
|
|
46
50
|
const TOOL_CANDIDATES = {
|
|
47
51
|
npm: ['npm', '/data/data/com.termux/files/usr/bin/npm'],
|
|
48
52
|
composer: ['composer', '/data/data/com.termux/files/usr/bin/composer'],
|
|
53
|
+
bundle: ['bundle', '/data/data/com.termux/files/usr/bin/bundle'],
|
|
54
|
+
cargo: ['cargo', '/data/data/com.termux/files/usr/bin/cargo'],
|
|
55
|
+
mvn: ['mvn', '/data/data/com.termux/files/usr/bin/mvn'],
|
|
56
|
+
gradle: ['gradle', '/data/data/com.termux/files/usr/bin/gradle'],
|
|
49
57
|
};
|
|
50
58
|
|
|
51
59
|
const TOOL_SMOKE_TESTS = {
|
|
52
60
|
npm: ['--version'],
|
|
53
61
|
composer: ['--version'],
|
|
62
|
+
bundle: ['--version'],
|
|
63
|
+
cargo: ['--version'],
|
|
64
|
+
mvn: ['--version'],
|
|
65
|
+
gradle: ['--version'],
|
|
54
66
|
};
|
|
55
67
|
|
|
56
68
|
const TOOL_PACKAGES = {
|
|
57
69
|
composer: ['composer'],
|
|
70
|
+
mvn: [],
|
|
71
|
+
gradle: [],
|
|
58
72
|
};
|
|
59
73
|
|
|
60
74
|
const PYTHON_IMPORT_TO_PACKAGE = {
|
|
@@ -97,31 +111,38 @@ export async function runInstallCommand() {
|
|
|
97
111
|
}
|
|
98
112
|
|
|
99
113
|
const projectContext = await detectProjectContext();
|
|
114
|
+
const platformMode = resolvePlatformMode(config);
|
|
100
115
|
if (!projectContext) {
|
|
101
|
-
throw new Error('No pude detectar el lenguaje del proyecto actual.');
|
|
116
|
+
throw new Error('No pude detectar el lenguaje del proyecto actual. Entra al root del proyecto o a una subcarpeta que pertenezca a uno.');
|
|
102
117
|
}
|
|
103
118
|
|
|
104
|
-
const
|
|
119
|
+
const currentDir = process.cwd();
|
|
120
|
+
const projectRoot = projectContext.projectRoot || currentDir;
|
|
105
121
|
const projectKey = getProjectKey(projectRoot);
|
|
106
122
|
const storedProjectState = config.projects?.[projectKey] || null;
|
|
107
123
|
const installMode = await detectInstallMode(projectContext.type, projectRoot);
|
|
108
|
-
const runtime = await ensureRuntimeAvailable(projectContext.type);
|
|
124
|
+
const runtime = await ensureRuntimeAvailable(projectContext.type, platformMode);
|
|
109
125
|
|
|
110
126
|
if (!runtime) {
|
|
111
|
-
throw new Error(
|
|
127
|
+
throw new Error(platformMode === 'termux'
|
|
128
|
+
? `No encontre el runtime para ${projectContext.label} en este entorno y tampoco pude instalarlo con pkg.`
|
|
129
|
+
: `No encontre el runtime para ${projectContext.label}. En modo Linux instala el runtime manualmente y luego vuelve a correr dex -i.`);
|
|
112
130
|
}
|
|
113
131
|
|
|
114
132
|
if (!installMode) {
|
|
115
133
|
throw new Error(
|
|
116
|
-
`Detecte ${projectContext.label}
|
|
134
|
+
`Detecte ${projectContext.label} en ${projectRoot}, pero no encontre un archivo o patron de instalacion que Dex sepa usar todavia.`,
|
|
117
135
|
);
|
|
118
136
|
}
|
|
119
137
|
|
|
120
|
-
const installCommand = await ensureInstallCommandAvailable(runtime, installMode);
|
|
121
|
-
const preferSafeMode = shouldUseSafeMode(projectContext.type, projectRoot, storedProjectState);
|
|
138
|
+
const installCommand = await ensureInstallCommandAvailable(runtime, installMode, platformMode);
|
|
139
|
+
const preferSafeMode = shouldUseSafeMode(projectContext.type, projectRoot, storedProjectState, platformMode);
|
|
122
140
|
|
|
123
141
|
printSection('Instalar Proyecto');
|
|
124
142
|
console.log(`Proyecto : ${projectRoot}`);
|
|
143
|
+
if (currentDir !== projectRoot) {
|
|
144
|
+
console.log(`Desde : ${currentDir}`);
|
|
145
|
+
}
|
|
125
146
|
console.log(`Lenguaje : ${projectContext.label}`);
|
|
126
147
|
console.log(`Modo : ${installMode.label}`);
|
|
127
148
|
console.log(`Runtime : ${runtime}`);
|
|
@@ -144,6 +165,7 @@ export async function runInstallCommand() {
|
|
|
144
165
|
projectKey,
|
|
145
166
|
projectContext,
|
|
146
167
|
reason: storedProjectState?.lastFailureReason || 'preferencia guardada',
|
|
168
|
+
platformMode,
|
|
147
169
|
});
|
|
148
170
|
return;
|
|
149
171
|
}
|
|
@@ -158,12 +180,15 @@ export async function runInstallCommand() {
|
|
|
158
180
|
return;
|
|
159
181
|
}
|
|
160
182
|
|
|
183
|
+
console.log('Dex nota: la instalacion normal fallo. Revisando rescate seguro...');
|
|
184
|
+
console.log('');
|
|
185
|
+
|
|
161
186
|
if (!supportsSafeMode(projectContext.type)) {
|
|
162
187
|
throw new Error(`La instalacion fallo y el rescate automatico aun no existe para ${projectContext.label}.`);
|
|
163
188
|
}
|
|
164
189
|
|
|
165
|
-
if (!isAndroidStoragePath(projectRoot)) {
|
|
166
|
-
throw new Error('La instalacion fallo y el proyecto no esta en Android storage.
|
|
190
|
+
if (shouldRestrictProjectToAndroidStorage(platformMode) && !isAndroidStoragePath(projectRoot)) {
|
|
191
|
+
throw new Error('La instalacion normal fallo y el proyecto no esta en Android storage. En Termux, el rescate automatico solo se aplica a proyectos dentro de /sdcard o /storage/emulated/0.');
|
|
167
192
|
}
|
|
168
193
|
|
|
169
194
|
await saveProjectState(projectKey, {
|
|
@@ -185,6 +210,7 @@ export async function runInstallCommand() {
|
|
|
185
210
|
projectKey,
|
|
186
211
|
projectContext,
|
|
187
212
|
reason: 'fallo instalacion normal en Android storage',
|
|
213
|
+
platformMode,
|
|
188
214
|
});
|
|
189
215
|
}
|
|
190
216
|
|
|
@@ -196,12 +222,13 @@ async function runSafeInstall({
|
|
|
196
222
|
projectKey,
|
|
197
223
|
projectContext,
|
|
198
224
|
reason,
|
|
225
|
+
platformMode,
|
|
199
226
|
}) {
|
|
200
227
|
if (!supportsSafeMode(projectContext.type)) {
|
|
201
228
|
throw new Error(`El modo seguro directo aun no existe para ${projectContext.label}.`);
|
|
202
229
|
}
|
|
203
230
|
|
|
204
|
-
if (!isAndroidStoragePath(projectRoot)) {
|
|
231
|
+
if (shouldRestrictProjectToAndroidStorage(platformMode) && !isAndroidStoragePath(projectRoot)) {
|
|
205
232
|
throw new Error('El modo seguro directo solo existe para proyectos dentro de Android storage.');
|
|
206
233
|
}
|
|
207
234
|
|
|
@@ -213,7 +240,7 @@ async function runSafeInstall({
|
|
|
213
240
|
console.log(`Regreso : ${projectRoot}`);
|
|
214
241
|
console.log('');
|
|
215
242
|
|
|
216
|
-
await ensurePythonSystemPackages(installMode);
|
|
243
|
+
await ensurePythonSystemPackages(installMode, platformMode);
|
|
217
244
|
await ensureRescueVenv(runtime, venvDir);
|
|
218
245
|
|
|
219
246
|
const rescuePython = path.join(venvDir, 'bin', 'python');
|
|
@@ -260,7 +287,7 @@ async function runSafeInstall({
|
|
|
260
287
|
console.log(`Origen : ${projectRoot}`);
|
|
261
288
|
console.log('');
|
|
262
289
|
|
|
263
|
-
await syncProjectToSafeWorkspace(projectRoot, safeProjectDir);
|
|
290
|
+
await syncProjectToSafeWorkspace(projectRoot, safeProjectDir, projectContext.type);
|
|
264
291
|
|
|
265
292
|
const rescueExitCode = await runCommand(installCommand, installMode.args, safeProjectDir);
|
|
266
293
|
if (rescueExitCode !== 0) {
|
|
@@ -305,7 +332,7 @@ async function runSafeInstall({
|
|
|
305
332
|
console.log(`Origen : ${projectRoot}`);
|
|
306
333
|
console.log('');
|
|
307
334
|
|
|
308
|
-
await syncProjectToSafeWorkspace(projectRoot, safeProjectDir);
|
|
335
|
+
await syncProjectToSafeWorkspace(projectRoot, safeProjectDir, projectContext.type);
|
|
309
336
|
|
|
310
337
|
const rescueExitCode = await runCommand(installCommand, installMode.args, safeProjectDir);
|
|
311
338
|
if (rescueExitCode !== 0) {
|
|
@@ -342,13 +369,58 @@ async function runSafeInstall({
|
|
|
342
369
|
return;
|
|
343
370
|
}
|
|
344
371
|
|
|
372
|
+
if (projectContext.type === 'ruby' || projectContext.type === 'go' || projectContext.type === 'rust' || projectContext.type === 'java') {
|
|
373
|
+
const safeProjectDir = getSafeProjectWorkspacePath(projectRoot, projectContext.type);
|
|
374
|
+
console.log(`Modo Dex : entrando directo al entorno seguro (${reason}).`);
|
|
375
|
+
console.log(`Base HOME: ${process.env.HOME || '/data/data/com.termux/files/home'}`);
|
|
376
|
+
console.log(`Seguro : ${safeProjectDir}`);
|
|
377
|
+
console.log(`Origen : ${projectRoot}`);
|
|
378
|
+
console.log('');
|
|
379
|
+
|
|
380
|
+
await syncProjectToSafeWorkspace(projectRoot, safeProjectDir, projectContext.type);
|
|
381
|
+
|
|
382
|
+
const rescueExitCode = await runCommand(installCommand, installMode.args, safeProjectDir);
|
|
383
|
+
if (rescueExitCode !== 0) {
|
|
384
|
+
await saveProjectState(projectKey, {
|
|
385
|
+
path: projectRoot,
|
|
386
|
+
language: projectContext.type,
|
|
387
|
+
preferSafeInstall: true,
|
|
388
|
+
lastFailureReason: 'fallo tambien en entorno seguro',
|
|
389
|
+
installModeLabel: installMode.label,
|
|
390
|
+
packages: installMode.packages || [],
|
|
391
|
+
safeMode: getSafeModeKind(projectContext.type),
|
|
392
|
+
safeWorkspacePath: safeProjectDir,
|
|
393
|
+
updatedAt: new Date().toISOString(),
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
throw new Error('La instalacion tambien fallo dentro del entorno seguro.');
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
await saveProjectState(projectKey, {
|
|
400
|
+
path: projectRoot,
|
|
401
|
+
language: projectContext.type,
|
|
402
|
+
preferSafeInstall: true,
|
|
403
|
+
lastFailureReason: '',
|
|
404
|
+
installModeLabel: installMode.label,
|
|
405
|
+
packages: installMode.packages || [],
|
|
406
|
+
safeMode: getSafeModeKind(projectContext.type),
|
|
407
|
+
safeWorkspacePath: safeProjectDir,
|
|
408
|
+
updatedAt: new Date().toISOString(),
|
|
409
|
+
lastSuccessAt: new Date().toISOString(),
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
console.log(`Instalacion completada usando espacio seguro de Dex para ${projectContext.label}.`);
|
|
413
|
+
console.log(`Seguro : ${safeProjectDir}`);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
|
|
345
417
|
throw new Error(`El modo seguro directo aun no existe para ${projectContext.label}.`);
|
|
346
418
|
}
|
|
347
419
|
|
|
348
|
-
function shouldUseSafeMode(projectType, projectRoot, projectState) {
|
|
420
|
+
function shouldUseSafeMode(projectType, projectRoot, projectState, platformMode) {
|
|
349
421
|
return Boolean(
|
|
350
422
|
supportsSafeMode(projectType)
|
|
351
|
-
&& isAndroidStoragePath(projectRoot)
|
|
423
|
+
&& (!shouldRestrictProjectToAndroidStorage(platformMode) || isAndroidStoragePath(projectRoot))
|
|
352
424
|
&& projectState?.preferSafeInstall,
|
|
353
425
|
);
|
|
354
426
|
}
|
|
@@ -412,6 +484,105 @@ async function detectInstallMode(projectType, projectRoot) {
|
|
|
412
484
|
}
|
|
413
485
|
}
|
|
414
486
|
|
|
487
|
+
if (projectType === 'ruby') {
|
|
488
|
+
const gemfileLockPath = path.join(projectRoot, 'Gemfile.lock');
|
|
489
|
+
if (await pathExists(gemfileLockPath)) {
|
|
490
|
+
return {
|
|
491
|
+
label: 'Gemfile.lock',
|
|
492
|
+
commandType: 'tool',
|
|
493
|
+
tool: 'bundle',
|
|
494
|
+
args: ['install'],
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
const gemfilePath = path.join(projectRoot, 'Gemfile');
|
|
499
|
+
if (await pathExists(gemfilePath)) {
|
|
500
|
+
return {
|
|
501
|
+
label: 'Gemfile',
|
|
502
|
+
commandType: 'tool',
|
|
503
|
+
tool: 'bundle',
|
|
504
|
+
args: ['install'],
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
if (projectType === 'go') {
|
|
510
|
+
const goModPath = path.join(projectRoot, 'go.mod');
|
|
511
|
+
if (await pathExists(goModPath)) {
|
|
512
|
+
return {
|
|
513
|
+
label: 'go.mod',
|
|
514
|
+
commandType: 'runtime',
|
|
515
|
+
args: ['mod', 'download'],
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
if (projectType === 'rust') {
|
|
521
|
+
const cargoLockPath = path.join(projectRoot, 'Cargo.lock');
|
|
522
|
+
if (await pathExists(cargoLockPath)) {
|
|
523
|
+
return {
|
|
524
|
+
label: 'Cargo.lock',
|
|
525
|
+
commandType: 'tool',
|
|
526
|
+
tool: 'cargo',
|
|
527
|
+
args: ['fetch'],
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
const cargoTomlPath = path.join(projectRoot, 'Cargo.toml');
|
|
532
|
+
if (await pathExists(cargoTomlPath)) {
|
|
533
|
+
return {
|
|
534
|
+
label: 'Cargo.toml',
|
|
535
|
+
commandType: 'tool',
|
|
536
|
+
tool: 'cargo',
|
|
537
|
+
args: ['fetch'],
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
if (projectType === 'java') {
|
|
543
|
+
const mavenWrapper = await findJavaWrapper(projectRoot, ['mvnw']);
|
|
544
|
+
const gradleWrapper = await findJavaWrapper(projectRoot, ['gradlew']);
|
|
545
|
+
const pomPath = path.join(projectRoot, 'pom.xml');
|
|
546
|
+
const gradlePath = path.join(projectRoot, 'build.gradle');
|
|
547
|
+
const gradleKtsPath = path.join(projectRoot, 'build.gradle.kts');
|
|
548
|
+
|
|
549
|
+
if (mavenWrapper && await pathExists(pomPath)) {
|
|
550
|
+
return {
|
|
551
|
+
label: path.basename(mavenWrapper),
|
|
552
|
+
commandType: 'local-script',
|
|
553
|
+
script: mavenWrapper,
|
|
554
|
+
args: ['dependency:go-offline'],
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
if (await pathExists(pomPath)) {
|
|
559
|
+
return {
|
|
560
|
+
label: 'pom.xml',
|
|
561
|
+
commandType: 'tool',
|
|
562
|
+
tool: 'mvn',
|
|
563
|
+
args: ['dependency:go-offline'],
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
if (gradleWrapper && (await pathExists(gradlePath) || await pathExists(gradleKtsPath))) {
|
|
568
|
+
return {
|
|
569
|
+
label: path.basename(gradleWrapper),
|
|
570
|
+
commandType: 'local-script',
|
|
571
|
+
script: gradleWrapper,
|
|
572
|
+
args: ['dependencies'],
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
if (await pathExists(gradlePath) || await pathExists(gradleKtsPath)) {
|
|
577
|
+
return {
|
|
578
|
+
label: (await pathExists(gradleKtsPath)) ? 'build.gradle.kts' : 'build.gradle',
|
|
579
|
+
commandType: 'tool',
|
|
580
|
+
tool: 'gradle',
|
|
581
|
+
args: ['dependencies'],
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
415
586
|
if (projectType !== 'python') {
|
|
416
587
|
return null;
|
|
417
588
|
}
|
|
@@ -456,18 +627,24 @@ async function detectInstallMode(projectType, projectRoot) {
|
|
|
456
627
|
return null;
|
|
457
628
|
}
|
|
458
629
|
|
|
459
|
-
async function ensureInstallCommandAvailable(runtime, installMode) {
|
|
630
|
+
async function ensureInstallCommandAvailable(runtime, installMode, platformMode) {
|
|
460
631
|
if (installMode.commandType === 'runtime') {
|
|
461
632
|
return runtime;
|
|
462
633
|
}
|
|
463
634
|
|
|
635
|
+
if (installMode.commandType === 'local-script' && installMode.script) {
|
|
636
|
+
return installMode.script;
|
|
637
|
+
}
|
|
638
|
+
|
|
464
639
|
if (installMode.commandType === 'tool' && installMode.tool) {
|
|
465
|
-
const tool = await ensureToolAvailable(installMode.tool);
|
|
640
|
+
const tool = await ensureToolAvailable(installMode.tool, platformMode);
|
|
466
641
|
if (tool) {
|
|
467
642
|
return tool;
|
|
468
643
|
}
|
|
469
644
|
|
|
470
|
-
throw new Error(
|
|
645
|
+
throw new Error(platformMode === 'termux'
|
|
646
|
+
? `No encontre la herramienta ${installMode.tool} para completar la instalacion segura.`
|
|
647
|
+
: `No encontre la herramienta ${installMode.tool}. En modo Linux instalala manualmente y vuelve a correr dex -i.`);
|
|
471
648
|
}
|
|
472
649
|
|
|
473
650
|
throw new Error('Dex no pudo resolver el comando de instalacion para este proyecto.');
|
|
@@ -593,12 +770,16 @@ function extractPythonImports(source) {
|
|
|
593
770
|
return modules;
|
|
594
771
|
}
|
|
595
772
|
|
|
596
|
-
async function ensureRuntimeAvailable(projectType) {
|
|
773
|
+
async function ensureRuntimeAvailable(projectType, platformMode) {
|
|
597
774
|
const runtime = await findRuntimeExecutable(projectType);
|
|
598
775
|
if (runtime) {
|
|
599
776
|
return runtime;
|
|
600
777
|
}
|
|
601
778
|
|
|
779
|
+
if (platformMode !== 'termux') {
|
|
780
|
+
return '';
|
|
781
|
+
}
|
|
782
|
+
|
|
602
783
|
const installed = await installRuntimeWithPkg(projectType);
|
|
603
784
|
if (!installed) {
|
|
604
785
|
return '';
|
|
@@ -635,12 +816,16 @@ async function findToolExecutable(toolName) {
|
|
|
635
816
|
return '';
|
|
636
817
|
}
|
|
637
818
|
|
|
638
|
-
async function ensureToolAvailable(toolName) {
|
|
819
|
+
async function ensureToolAvailable(toolName, platformMode) {
|
|
639
820
|
const tool = await findToolExecutable(toolName);
|
|
640
821
|
if (tool) {
|
|
641
822
|
return tool;
|
|
642
823
|
}
|
|
643
824
|
|
|
825
|
+
if (platformMode !== 'termux') {
|
|
826
|
+
return '';
|
|
827
|
+
}
|
|
828
|
+
|
|
644
829
|
const installed = await installToolWithPkg(toolName);
|
|
645
830
|
if (!installed) {
|
|
646
831
|
return '';
|
|
@@ -701,7 +886,11 @@ function throwPkgInstallError(projectType, output) {
|
|
|
701
886
|
throw new Error(`No pude instalar ${projectType} con pkg. Revisa la salida anterior para ver el motivo exacto.`);
|
|
702
887
|
}
|
|
703
888
|
|
|
704
|
-
async function ensurePythonSystemPackages(installMode) {
|
|
889
|
+
async function ensurePythonSystemPackages(installMode, platformMode) {
|
|
890
|
+
if (platformMode !== 'termux') {
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
893
|
+
|
|
705
894
|
const packages = gatherSystemPackagesForPythonInstall(installMode);
|
|
706
895
|
if (!packages.length) {
|
|
707
896
|
return;
|
|
@@ -868,9 +1057,37 @@ function getSafeProjectWorkspacePath(projectRoot, projectType) {
|
|
|
868
1057
|
return path.join(home, '.dex', 'projects', safeKind, `${safeName}-${digest}`);
|
|
869
1058
|
}
|
|
870
1059
|
|
|
871
|
-
async function syncProjectToSafeWorkspace(projectRoot, safeProjectDir) {
|
|
1060
|
+
async function syncProjectToSafeWorkspace(projectRoot, safeProjectDir, projectType) {
|
|
872
1061
|
await fs.mkdir(safeProjectDir, { recursive: true });
|
|
1062
|
+
await resetDirectoryContents(safeProjectDir);
|
|
873
1063
|
await copyDirectoryRecursive(projectRoot, safeProjectDir);
|
|
1064
|
+
await writeSafeWorkspaceMeta(safeProjectDir, projectRoot, projectType);
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
async function resetDirectoryContents(targetDir) {
|
|
1068
|
+
let entries = [];
|
|
1069
|
+
|
|
1070
|
+
try {
|
|
1071
|
+
entries = await fs.readdir(targetDir, { withFileTypes: true });
|
|
1072
|
+
} catch {
|
|
1073
|
+
return;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
for (const entry of entries) {
|
|
1077
|
+
await fs.rm(path.join(targetDir, entry.name), { recursive: true, force: true });
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
async function writeSafeWorkspaceMeta(safeProjectDir, projectRoot, projectType) {
|
|
1082
|
+
const metadataPath = path.join(safeProjectDir, '.dex-workspace.json');
|
|
1083
|
+
const metadata = {
|
|
1084
|
+
projectRoot,
|
|
1085
|
+
projectType,
|
|
1086
|
+
generatedAt: new Date().toISOString(),
|
|
1087
|
+
};
|
|
1088
|
+
|
|
1089
|
+
await fs.writeFile(metadataPath, `${JSON.stringify(metadata, null, 2)}
|
|
1090
|
+
`, 'utf8');
|
|
874
1091
|
}
|
|
875
1092
|
|
|
876
1093
|
async function copyDirectoryRecursive(sourceDir, targetDir) {
|
|
@@ -904,11 +1121,21 @@ async function copyDirectoryRecursive(sourceDir, targetDir) {
|
|
|
904
1121
|
|
|
905
1122
|
function shouldSkipSafeCopy(name) {
|
|
906
1123
|
return name === '.git'
|
|
907
|
-
|| name === '
|
|
908
|
-
|| name === '
|
|
1124
|
+
|| name === '.gradle'
|
|
1125
|
+
|| name === '.idea'
|
|
1126
|
+
|| name === '.vscode'
|
|
1127
|
+
|| name === '.mypy_cache'
|
|
1128
|
+
|| name === '.pytest_cache'
|
|
1129
|
+
|| name === '.ruff_cache'
|
|
909
1130
|
|| name === '.venv'
|
|
910
1131
|
|| name === 'venv'
|
|
911
|
-
|| name === '__pycache__'
|
|
1132
|
+
|| name === '__pycache__'
|
|
1133
|
+
|| name === 'node_modules'
|
|
1134
|
+
|| name === 'vendor'
|
|
1135
|
+
|| name === 'target'
|
|
1136
|
+
|| name === 'dist'
|
|
1137
|
+
|| name === 'build'
|
|
1138
|
+
|| name === 'bin';
|
|
912
1139
|
}
|
|
913
1140
|
|
|
914
1141
|
async function pathExists(targetPath) {
|
|
@@ -920,12 +1147,20 @@ async function pathExists(targetPath) {
|
|
|
920
1147
|
}
|
|
921
1148
|
}
|
|
922
1149
|
|
|
923
|
-
|
|
924
|
-
|
|
1150
|
+
|
|
1151
|
+
async function findJavaWrapper(projectRoot, names) {
|
|
1152
|
+
for (const name of names) {
|
|
1153
|
+
const targetPath = path.join(projectRoot, name);
|
|
1154
|
+
if (await pathExists(targetPath)) {
|
|
1155
|
+
return targetPath;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
return '';
|
|
925
1160
|
}
|
|
926
1161
|
|
|
927
1162
|
function supportsSafeMode(projectType) {
|
|
928
|
-
return projectType === 'python' || projectType === 'node' || projectType === 'php';
|
|
1163
|
+
return projectType === 'python' || projectType === 'node' || projectType === 'php' || projectType === 'ruby' || projectType === 'go' || projectType === 'rust' || projectType === 'java';
|
|
929
1164
|
}
|
|
930
1165
|
|
|
931
1166
|
function getSafeModeKind(projectType) {
|
|
@@ -941,6 +1176,22 @@ function getSafeModeKind(projectType) {
|
|
|
941
1176
|
return 'php-workspace';
|
|
942
1177
|
}
|
|
943
1178
|
|
|
1179
|
+
if (projectType === 'ruby') {
|
|
1180
|
+
return 'ruby-workspace';
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
if (projectType === 'go') {
|
|
1184
|
+
return 'go-workspace';
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
if (projectType === 'rust') {
|
|
1188
|
+
return 'rust-workspace';
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
if (projectType === 'java') {
|
|
1192
|
+
return 'java-workspace';
|
|
1193
|
+
}
|
|
1194
|
+
|
|
944
1195
|
return '';
|
|
945
1196
|
}
|
|
946
1197
|
|
package/src/commands/menu.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
loadUserConfig,
|
|
3
|
+
setFeatureEnabled,
|
|
4
|
+
setPlatformMode,
|
|
5
|
+
setPromptContextPosition,
|
|
6
|
+
} from '../core/config.js';
|
|
7
|
+
import { formatPlatformMode, resolvePlatformMode } from '../utils/platform.js';
|
|
2
8
|
import { runContextCommand } from './context.js';
|
|
3
9
|
import { runExplainCommand } from './explain.js';
|
|
4
10
|
import { runSafeShellCommand } from './safe-shell.js';
|
|
@@ -8,6 +14,7 @@ import { runVersionCommand } from './version.js';
|
|
|
8
14
|
import {
|
|
9
15
|
chooseFeatureToggle,
|
|
10
16
|
chooseMenuAction,
|
|
17
|
+
choosePlatformMode,
|
|
11
18
|
choosePromptContextPosition,
|
|
12
19
|
chooseSearchPatternFromMenu,
|
|
13
20
|
chooseSettingsAction,
|
|
@@ -77,11 +84,25 @@ async function runSettingsMenu() {
|
|
|
77
84
|
return;
|
|
78
85
|
}
|
|
79
86
|
|
|
87
|
+
if (action === 'platform-mode') {
|
|
88
|
+
const currentMode = formatPlatformMode(resolvePlatformMode(config));
|
|
89
|
+
const mode = await choosePlatformMode(currentMode);
|
|
90
|
+
|
|
91
|
+
if (mode === 'back') {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
await setPlatformMode(mode);
|
|
96
|
+
console.log('Modo de plataforma: ' + formatPlatformModeLabel(mode) + '.');
|
|
97
|
+
console.log('');
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
|
|
80
101
|
if (action === 'toggle-android-shortcut') {
|
|
81
102
|
const toggle = await chooseFeatureToggle(
|
|
82
103
|
config.features.androidShortcut,
|
|
83
|
-
'Acceso rapido
|
|
84
|
-
'permite usar dex -a o
|
|
104
|
+
'Acceso rapido',
|
|
105
|
+
'permite usar dex -a en Termux o Linux',
|
|
85
106
|
);
|
|
86
107
|
|
|
87
108
|
if (toggle === 'back') {
|
|
@@ -90,7 +111,7 @@ async function runSettingsMenu() {
|
|
|
90
111
|
|
|
91
112
|
const enabled = toggle === 'enable';
|
|
92
113
|
await setFeatureEnabled('androidShortcut', enabled);
|
|
93
|
-
console.log(`Acceso rapido
|
|
114
|
+
console.log(`Acceso rapido: ${enabled ? 'activado' : 'desactivado'}.`);
|
|
94
115
|
console.log('');
|
|
95
116
|
continue;
|
|
96
117
|
}
|
|
@@ -130,7 +151,7 @@ async function runSettingsMenu() {
|
|
|
130
151
|
const toggle = await chooseFeatureToggle(
|
|
131
152
|
config.features.smartProjectInstall,
|
|
132
153
|
'Instalacion segura de proyectos',
|
|
133
|
-
'
|
|
154
|
+
'rescata instalaciones y puede instalar runtimes con pkg en Termux',
|
|
134
155
|
);
|
|
135
156
|
|
|
136
157
|
if (toggle === 'back') {
|
|
@@ -156,3 +177,15 @@ function formatPromptContextPosition(position) {
|
|
|
156
177
|
|
|
157
178
|
return 'a la derecha';
|
|
158
179
|
}
|
|
180
|
+
|
|
181
|
+
function formatPlatformModeLabel(mode) {
|
|
182
|
+
if (mode === 'linux') {
|
|
183
|
+
return 'linux';
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (mode === 'termux') {
|
|
187
|
+
return 'termux';
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return 'auto';
|
|
191
|
+
}
|