Enhance convert_path_with_tilde_expansion to handle Windows (#4390)
This commit is contained in:
@@ -36,11 +36,25 @@ pub fn read_recipe_file<P: AsRef<Path>>(recipe_path: P) -> Result<RecipeFile> {
|
|||||||
|
|
||||||
fn convert_path_with_tilde_expansion(path: &Path) -> PathBuf {
|
fn convert_path_with_tilde_expansion(path: &Path) -> PathBuf {
|
||||||
if let Some(path_str) = path.to_str() {
|
if let Some(path_str) = path.to_str() {
|
||||||
|
// Handle exact "~" (Windows only to avoid changing behavior on Unix)
|
||||||
|
if cfg!(windows) && path_str == "~" {
|
||||||
|
if let Some(home_dir) = dirs::home_dir() {
|
||||||
|
return home_dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Handle Unix-style "~/..."
|
||||||
if let Some(stripped) = path_str.strip_prefix("~/") {
|
if let Some(stripped) = path_str.strip_prefix("~/") {
|
||||||
if let Some(home_dir) = dirs::home_dir() {
|
if let Some(home_dir) = dirs::home_dir() {
|
||||||
return home_dir.join(stripped);
|
return home_dir.join(stripped);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Handle Windows-style "~\\..." (Windows only)
|
||||||
|
#[cfg(windows)]
|
||||||
|
if let Some(stripped) = path_str.strip_prefix("~\\") {
|
||||||
|
if let Some(home_dir) = dirs::home_dir() {
|
||||||
|
return home_dir.join(stripped);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
PathBuf::from(path)
|
PathBuf::from(path)
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-27
@@ -1581,37 +1581,44 @@ ipcMain.handle('get-binary-path', (_event, binaryName) => {
|
|||||||
return getBinaryPath(app, binaryName);
|
return getBinaryPath(app, binaryName);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('read-file', (_event, filePath) => {
|
ipcMain.handle('read-file', async (_event, filePath) => {
|
||||||
return new Promise((resolve) => {
|
try {
|
||||||
// Expand tilde to home directory
|
|
||||||
const expandedPath = expandTilde(filePath);
|
const expandedPath = expandTilde(filePath);
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
const buffer = await fs.readFile(expandedPath);
|
||||||
|
return { file: buffer.toString('utf8'), filePath: expandedPath, error: null, found: true };
|
||||||
|
}
|
||||||
|
// Non-Windows: keep previous behavior via cat for parity
|
||||||
|
return await new Promise((resolve) => {
|
||||||
|
const cat = spawn('cat', [expandedPath]);
|
||||||
|
let output = '';
|
||||||
|
let errorOutput = '';
|
||||||
|
|
||||||
const cat = spawn('cat', [expandedPath]);
|
cat.stdout.on('data', (data) => {
|
||||||
let output = '';
|
output += data.toString();
|
||||||
let errorOutput = '';
|
});
|
||||||
|
|
||||||
cat.stdout.on('data', (data) => {
|
cat.stderr.on('data', (data) => {
|
||||||
output += data.toString();
|
errorOutput += data.toString();
|
||||||
|
});
|
||||||
|
|
||||||
|
cat.on('close', (code) => {
|
||||||
|
if (code !== 0) {
|
||||||
|
resolve({ file: '', filePath: expandedPath, error: errorOutput || null, found: false });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve({ file: output, filePath: expandedPath, error: null, found: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
cat.on('error', (error) => {
|
||||||
|
console.error('Error reading file:', error);
|
||||||
|
resolve({ file: '', filePath: expandedPath, error, found: false });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
} catch (error) {
|
||||||
cat.stderr.on('data', (data) => {
|
console.error('Error reading file:', error);
|
||||||
errorOutput += data.toString();
|
return { file: '', filePath: expandTilde(filePath), error, found: false };
|
||||||
});
|
}
|
||||||
|
|
||||||
cat.on('close', (code) => {
|
|
||||||
if (code !== 0) {
|
|
||||||
// File not found or error
|
|
||||||
resolve({ file: '', filePath: expandedPath, error: errorOutput || null, found: false });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
resolve({ file: output, filePath: expandedPath, error: null, found: true });
|
|
||||||
});
|
|
||||||
|
|
||||||
cat.on('error', (error) => {
|
|
||||||
console.error('Error reading file:', error);
|
|
||||||
resolve({ file: '', filePath: expandedPath, error, found: false });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('write-file', async (_event, filePath, content) => {
|
ipcMain.handle('write-file', async (_event, filePath, content) => {
|
||||||
|
|||||||
@@ -119,7 +119,18 @@ const addPaths = (
|
|||||||
* @returns The expanded path with tilde replaced by home directory
|
* @returns The expanded path with tilde replaced by home directory
|
||||||
*/
|
*/
|
||||||
export function expandTilde(filePath: string): string {
|
export function expandTilde(filePath: string): string {
|
||||||
|
if (!filePath || typeof filePath !== 'string') return filePath;
|
||||||
|
// Support "~", "~/..." and "~\\..." on Windows
|
||||||
|
if (filePath === '~') {
|
||||||
|
return os.homedir();
|
||||||
|
}
|
||||||
|
if (filePath.startsWith('~/') || (process.platform === 'win32' && filePath.startsWith('~\\'))) {
|
||||||
|
// Remove the leading "~" and any separator that follows, then join
|
||||||
|
const remainder = filePath.slice(2);
|
||||||
|
return path.join(os.homedir(), remainder);
|
||||||
|
}
|
||||||
if (filePath.startsWith('~')) {
|
if (filePath.startsWith('~')) {
|
||||||
|
// Generic fallback: replace only the first leading tilde
|
||||||
return path.join(os.homedir(), filePath.slice(1));
|
return path.join(os.homedir(), filePath.slice(1));
|
||||||
}
|
}
|
||||||
return filePath;
|
return filePath;
|
||||||
|
|||||||
Reference in New Issue
Block a user