Skip to content

Commit d11033a

Browse files
authored
Merge pull request #225 from netease-youdao/fix/windows-gitbash
fix: 修复 Windows 端提示缺少 git bash 的问题
2 parents b71675a + 4ca5f85 commit d11033a

3 files changed

Lines changed: 78 additions & 4 deletions

File tree

scripts/electron-builder-hooks.cjs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22

33
const path = require('path');
4-
const { existsSync, readdirSync, statSync } = require('fs');
4+
const { existsSync, mkdirSync, readdirSync, statSync } = require('fs');
55
const { spawnSync } = require('child_process');
66
const { ensurePortableGit } = require('./setup-mingit.js');
77
const { ensurePortablePythonRuntime, checkRuntimeHealth } = require('./setup-python-runtime.js');
@@ -29,6 +29,40 @@ function findPackagedBash(appOutDir) {
2929
return null;
3030
}
3131

32+
function verifyPackagedPortableGitRuntimeDirs(appOutDir) {
33+
const requiredDirs = [
34+
path.join(appOutDir, 'resources', 'mingit', 'dev', 'shm'),
35+
path.join(appOutDir, 'resources', 'mingit', 'dev', 'mqueue'),
36+
];
37+
const createdDirs = [];
38+
39+
for (const dir of requiredDirs) {
40+
if (existsSync(dir)) continue;
41+
mkdirSync(dir, { recursive: true });
42+
createdDirs.push(dir);
43+
}
44+
45+
const missingDirs = requiredDirs.filter((dir) => !existsSync(dir));
46+
if (missingDirs.length > 0) {
47+
throw new Error(
48+
'Windows package is missing required PortableGit runtime directories. '
49+
+ `Missing: ${missingDirs.join(', ')}`
50+
);
51+
}
52+
53+
if (createdDirs.length > 0) {
54+
console.log(
55+
'[electron-builder-hooks] Created missing PortableGit runtime directories: '
56+
+ createdDirs.join(', ')
57+
);
58+
}
59+
60+
console.log(
61+
'[electron-builder-hooks] Verified PortableGit runtime directories: '
62+
+ requiredDirs.join(', ')
63+
);
64+
}
65+
3266
function findPackagedPythonExecutable(appOutDir) {
3367
const candidates = [
3468
path.join(appOutDir, 'resources', 'python-win', 'python.exe'),
@@ -380,6 +414,7 @@ async function afterPack(context) {
380414
}
381415

382416
console.log(`[electron-builder-hooks] Verified bundled PortableGit: ${bashPath}`);
417+
verifyPackagedPortableGitRuntimeDirs(context.appOutDir);
383418

384419
const pythonExe = findPackagedPythonExecutable(context.appOutDir);
385420
if (!pythonExe) {

scripts/setup-mingit.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ const DEFAULT_PORTABLE_GIT_URL =
2626
const PROJECT_ROOT = path.resolve(__dirname, '..');
2727
const OUTPUT_DIR = path.join(PROJECT_ROOT, 'resources', 'mingit');
2828
const DEFAULT_ARCHIVE_PATH = path.join(PROJECT_ROOT, 'resources', PORTABLE_GIT_FILE);
29+
const RUNTIME_DIRS = [
30+
path.join('dev', 'shm'),
31+
path.join('dev', 'mqueue'),
32+
];
2933

3034
const DIRS_TO_PRUNE = [
3135
'doc',
@@ -176,6 +180,27 @@ function extractArchive(archivePath) {
176180
}
177181
}
178182

183+
function ensurePortableGitRuntimeDirs(required) {
184+
const ensured = [];
185+
for (const relPath of RUNTIME_DIRS) {
186+
const fullPath = path.join(OUTPUT_DIR, relPath);
187+
try {
188+
fs.mkdirSync(fullPath, { recursive: true });
189+
ensured.push(relPath);
190+
} catch (error) {
191+
const message = `Could not create runtime directory ${relPath}: ${error instanceof Error ? error.message : String(error)}`;
192+
if (required) {
193+
throw new Error(message);
194+
}
195+
console.warn(`[setup-mingit] Warning: ${message}`);
196+
}
197+
}
198+
199+
if (ensured.length > 0) {
200+
console.log(`[setup-mingit] Ensured runtime directories: ${ensured.join(', ')}`);
201+
}
202+
}
203+
179204
async function resolveArchive(required) {
180205
const envArchive = resolveInputPath(process.env.LOBSTERAI_PORTABLE_GIT_ARCHIVE);
181206
if (envArchive) {
@@ -233,6 +258,7 @@ async function ensurePortableGit(options = {}) {
233258

234259
const existingBash = findPortableGitBash();
235260
if (existingBash) {
261+
ensurePortableGitRuntimeDirs(required);
236262
console.log(`[setup-mingit] PortableGit already prepared: ${existingBash}`);
237263
return { ok: true, skipped: false, bashPath: existingBash };
238264
}
@@ -251,6 +277,7 @@ async function ensurePortableGit(options = {}) {
251277
);
252278
}
253279

280+
ensurePortableGitRuntimeDirs(required);
254281
pruneUnneededFiles();
255282

256283
const finalSize = getDirSize(OUTPUT_DIR);

src/main/libs/coworkUtil.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,21 @@ function checkWindowsGitBashHealth(bashPath: string): { ok: boolean; reason?: st
278278
};
279279
}
280280

281-
const output = (result.stdout || '').trim();
282-
if (!output.startsWith('/')) {
283-
return { ok: false, reason: `unexpected cygpath output: ${output || '(empty)'}` };
281+
const stdout = (result.stdout || '').trim();
282+
const stderr = (result.stderr || '').trim();
283+
const lines = stdout
284+
.split(/\r?\n/)
285+
.map((line) => line.trim())
286+
.filter(Boolean);
287+
const lastNonEmptyLine = lines.length > 0 ? lines[lines.length - 1] : '';
288+
289+
// Some Git Bash builds may print runtime warnings before the actual cygpath
290+
// output (for example, missing /dev/shm or /dev/mqueue directories).
291+
// Accept the check when the final non-empty line is a valid POSIX path.
292+
if (!/^\/[a-zA-Z]\//.test(lastNonEmptyLine)) {
293+
const diagnosticStdout = truncateDiagnostic(stdout || '(empty)');
294+
const diagnosticStderr = stderr ? `, stderr: ${truncateDiagnostic(stderr)}` : '';
295+
return { ok: false, reason: `unexpected cygpath output: ${diagnosticStdout}${diagnosticStderr}` };
284296
}
285297

286298
return { ok: true };

0 commit comments

Comments
 (0)