v2.2.2: Fix bootstrap permission denied - chmod after install, shell fallback, fixPermissions plugin method

This commit is contained in:
admin
2026-05-19 20:05:13 +04:00
Unverified
parent 9880baac5b
commit f3b2150cb0
7 changed files with 154 additions and 50 deletions

View File

@@ -1911,6 +1911,8 @@
return true;
}
try { await Bootstrap.fixPermissions(); } catch(e) {}
if (Shell) {
var env = await Shell.getEnv();
termState.homeDir = env.HOME;
@@ -1919,53 +1921,50 @@
termState.cwd = env.CWD || env.HOME;
}
var prefix = termState.homeDir ? termState.homeDir.replace('/home', '') + '/usr' : '';
var pkgBin = prefix + '/bin/pkg';
var aptBin = prefix + '/bin/apt';
var prefix = termState.homeDir ? termState.homeDir.replace('/home', '') : termState.homeDir || '';
var prefixUsr = prefix + '/usr';
var pkgBin = prefixUsr + '/bin/pkg';
var aptBin = prefixUsr + '/bin/apt';
var pkgExists = await shellExec('test -x "' + pkgBin + '"', termState.homeDir, false);
var aptExists = await shellExec('test -x "' + aptBin + '"', termState.homeDir, false);
var pkgTest = await shellExec('test -f "' + pkgBin + '"', termState.homeDir, false);
var aptTest = await shellExec('test -f "' + aptBin + '"', termState.homeDir, false);
if (pkgExists.exitCode !== 0 && aptExists.exitCode !== 0) {
termPrint('[!] No package manager found. Install Termux bootstrap first.', 'err');
if (pkgTest.exitCode !== 0 && aptTest.exitCode !== 0) {
var bsStatus;
try { bsStatus = await Bootstrap.getStatus(); } catch(e) { bsStatus = { installed: false }; }
if (!bsStatus.installed) {
termPrint('[!] Termux bootstrap not installed yet.', 'err');
} else {
termPrint('[!] Package manager not found at ' + pkgBin, 'err');
}
termState.devToolsInstalled = false;
return false;
}
termPrint('[*] Installing build tools (aapt2, ecj, dx, apksigner)...', 'info');
termPrint('[*] This may take a few minutes on first run...', 'info');
termPrint('[*] This may take a few minutes...', 'info');
showStatusToast('Installing build tools...', 'info');
var installCmd;
if (pkgExists.exitCode === 0) {
installCmd = pkgBin + ' update -y 2>&1 && ' + pkgBin + ' install -y aapt2 ecj dx apksigner 2>&1';
} else {
installCmd = aptBin + ' update -y 2>&1 && ' + aptBin + ' install -y aapt2 ecj dx apksigner 2>&1';
var methods = [];
if (pkgTest.exitCode === 0) {
methods.push('chmod 755 "' + pkgBin + '" 2>/dev/null; "' + pkgBin + '" update -y 2>&1 && "' + pkgBin + '" install -y aapt2 ecj dx apksigner 2>&1');
}
if (aptTest.exitCode === 0) {
methods.push('chmod 755 "' + aptBin + '" 2>/dev/null; "' + aptBin + '" update -y 2>&1 && "' + aptBin + '" install -y aapt2 ecj dx apksigner 2>&1');
}
var installResult = await shellExec(installCmd, termState.homeDir, false);
if (installResult.output) {
var out = installResult.output;
if (out.length > 2000) out = out.substring(0, 1000) + '\n... truncated ...\n' + out.substring(out.length - 800);
termPrint(out.replace(/\n$/, ''), '');
}
for (var m = 0; m < methods.length; m++) {
termPrint('[*] Attempt ' + (m + 1) + '...', 'info');
var installResult = await shellExec(methods[m], termState.homeDir, false);
if (installResult.output) {
var out = installResult.output;
if (out.length > 2000) out = out.substring(0, 1000) + '\n... truncated ...\n' + out.substring(out.length - 800);
termPrint(out.replace(/\n$/, ''), '');
}
var recheck = await shellExec('command -v aapt2 >/dev/null 2>&1 && command -v ecj >/dev/null 2>&1', termState.homeDir, false);
if (recheck.exitCode === 0) {
termPrint('[OK] Build tools installed successfully!', 'success');
showStatusToast('Build tools installed!', 'success');
termState.devToolsInstalled = true;
return true;
}
if (pkgExists.exitCode === 0 && installResult.exitCode !== 0) {
termPrint('[*] Retrying with apt directly...', 'info');
var retryResult = await shellExec(aptBin + ' update 2>&1 && ' + aptBin + ' install -y aapt2 ecj dx apksigner 2>&1', termState.homeDir, false);
if (retryResult.output) termPrint(retryResult.output.substring(0, 1500).replace(/\n$/, ''), '');
var recheck2 = await shellExec('command -v aapt2 >/dev/null 2>&1 && command -v ecj >/dev/null 2>&1', termState.homeDir, false);
if (recheck2.exitCode === 0) {
termPrint('[OK] Build tools installed!', 'success');
var recheck = await shellExec('command -v aapt2 >/dev/null 2>&1 && command -v ecj >/dev/null 2>&1', termState.homeDir, false);
if (recheck.exitCode === 0) {
termPrint('[OK] Build tools installed successfully!', 'success');
showStatusToast('Build tools installed!', 'success');
termState.devToolsInstalled = true;
return true;
@@ -2029,6 +2028,7 @@
if (!bsStatus.installed) {
try {
await Bootstrap.install();
try { await Bootstrap.fixPermissions(); } catch(e) {}
if (Shell) {
var env = await Shell.getEnv();
termState.homeDir = env.HOME;
@@ -2037,8 +2037,9 @@
termState.cwd = env.CWD || env.HOME;
}
updateCwdDisplay();
await shellExec('echo shell-ok', termState.homeDir, false);
} catch(e) {
btn.textContent = 'Bootstrap failed';
btn.textContent = 'Bootstrap failed: ' + e.message;
return;
}
}
@@ -2355,14 +2356,10 @@
try {
var result = await Bootstrap.install();
statusEl.innerHTML = '<p style="color:var(--success);font-size:16px;font-weight:700">&#10004; Termux environment installed!</p>' +
'<p>Full Linux shell with bash, coreutils, and package manager ready.</p>' +
'<p id="devsetup-tools-status">Installing build tools (aapt2, ecj, d8, apksigner)...</p>';
btn.querySelector('.btn-text').textContent = 'Installed';
btn.querySelector('.btn-loader').style.display = 'none';
termState.homeDir = result.prefixDir ? result.prefixDir.replace('/usr', '') : termState.homeDir;
termState.cwd = termState.homeDir + '/home';
progressText.textContent = 'Fixing file permissions...';
try { await Bootstrap.fixPermissions(); } catch(e) {}
if (Shell) {
var env = await Shell.getEnv();
termState.homeDir = env.HOME;
@@ -2372,13 +2369,29 @@
}
updateCwdDisplay();
var shellTest = await shellExec('echo OK', termState.homeDir, false);
if (shellTest.exitCode !== 0) {
statusEl.innerHTML = '<p style="color:var(--danger)">Shell test failed: ' + (shellTest.output || 'unknown error') + '</p>' +
'<p>Try restarting the app.</p>';
btn.disabled = false;
btn.querySelector('.btn-text').textContent = 'Retry Install';
btn.querySelector('.btn-loader').style.display = 'none';
return;
}
statusEl.innerHTML = '<p style="color:var(--success);font-size:16px;font-weight:700">&#10004; Termux environment installed!</p>' +
'<p id="devsetup-tools-status">Installing build tools (aapt2, ecj, d8, apksigner)...</p>';
var toolsOk = await ensureBuildTools();
var toolsStatus = $('#devsetup-tools-status');
if (toolsStatus) {
toolsStatus.innerHTML = toolsOk
? '<span style="color:var(--success)">&#10004; Build tools installed (aapt2, ecj, d8, apksigner)</span>'
: '<span style="color:var(--warning)">Build tools not installed. Run: pkg install aapt2 ecj dx apksigner</span>';
? '<span style="color:var(--success)">&#10004; All tools installed — ready to build!</span>'
: '<span style="color:var(--warning)">Build tools not installed. Open Terminal and run: pkg install aapt2 ecj dx apksigner</span>';
}
btn.querySelector('.btn-text').textContent = 'Installed';
btn.querySelector('.btn-loader').style.display = 'none';
} catch(e) {
statusEl.innerHTML = '<p style="color:var(--danger)">Install failed: ' + e.message + '</p>' +
'<p>Check your internet connection and try again.</p>';