Skip to content

Commit e5ccde9

Browse files
committed
Expand tilde (~) in config paths like derivedDataPath (#283)
Paths containing ~ (e.g. ~/.derivedData) were not expanded, causing a literal ~ directory to be created in the project root. Add tilde expansion in both path resolution functions: - resolvePathFromCwd in build-utils.ts (runtime path resolution) - normalizePathValue in project-config.ts (config YAML loading) This allows shared config files to use ~/... paths that work across team members with different home directories.
1 parent 301ca03 commit e5ccde9

File tree

4 files changed

+72
-0
lines changed

4 files changed

+72
-0
lines changed

src/utils/__tests__/build-utils.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,5 +387,41 @@ describe('build-utils Sentry Classification', () => {
387387
expect(capturedCommand).toContain(expectedDerivedDataPath);
388388
expect(capturedOptions).toEqual({ cwd: path.dirname(expectedProjectPath) });
389389
});
390+
391+
it('should expand tilde in derivedDataPath to home directory', async () => {
392+
let capturedCommand: string[] | undefined;
393+
const mockExecutor = createMockExecutor({
394+
success: true,
395+
output: 'BUILD SUCCEEDED',
396+
exitCode: 0,
397+
onExecute: (command) => {
398+
capturedCommand = command;
399+
},
400+
});
401+
402+
const { homedir } = await import('os');
403+
const expectedDerivedDataPath = path.join(homedir(), '.derivedData/test');
404+
405+
await executeXcodeBuildCommand(
406+
{
407+
scheme: 'TestScheme',
408+
configuration: 'Debug',
409+
projectPath: '/path/to/project.xcodeproj',
410+
derivedDataPath: '~/.derivedData/test',
411+
},
412+
{
413+
platform: XcodePlatform.iOSSimulator,
414+
simulatorName: 'iPhone 17 Pro',
415+
useLatestOS: true,
416+
logPrefix: 'iOS Simulator Build',
417+
},
418+
false,
419+
'build',
420+
mockExecutor,
421+
);
422+
423+
expect(capturedCommand).toBeDefined();
424+
expect(capturedCommand).toContain(expectedDerivedDataPath);
425+
});
390426
});
391427
});

src/utils/__tests__/project-config.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { describe, expect, it } from 'vitest';
22
import path from 'node:path';
3+
import { homedir } from 'node:os';
34
import { parse as parseYaml } from 'yaml';
45
import { createMockFileSystemExecutor } from '../../test-utils/mock-executors.ts';
56
import {
@@ -187,6 +188,25 @@ describe('project-config', () => {
187188
);
188189
});
189190

191+
it('should expand tilde in derivedDataPath and other path fields', async () => {
192+
const yaml = [
193+
'schemaVersion: 1',
194+
'sessionDefaults:',
195+
' workspacePath: "./App.xcworkspace"',
196+
' derivedDataPath: "~/.derivedData/myproject"',
197+
'',
198+
].join('\n');
199+
200+
const { fs } = createFsFixture({ exists: true, readFile: yaml });
201+
const result = await loadProjectConfig({ fs, cwd });
202+
203+
if (!result.found) throw new Error('expected config to be found');
204+
205+
const defaults = result.config.sessionDefaults ?? {};
206+
expect(defaults.derivedDataPath).toBe(path.join(homedir(), '.derivedData', 'myproject'));
207+
expect(defaults.workspacePath).toBe(path.join(cwd, 'App.xcworkspace'));
208+
});
209+
190210
it('should return an error result when schemaVersion is unsupported', async () => {
191211
const yaml = ['schemaVersion: 2', 'sessionDefaults:', ' scheme: "App"', ''].join('\n');
192212
const { fs } = createFsFixture({ exists: true, readFile: yaml });

src/utils/build-utils.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,15 @@ import {
3232
} from './xcodemake.ts';
3333
import { sessionStore } from './session-store.ts';
3434
import path from 'path';
35+
import { homedir } from 'os';
3536

3637
function resolvePathFromCwd(pathValue: string): string {
38+
if (pathValue === '~') {
39+
return homedir();
40+
}
41+
if (pathValue.startsWith('~/')) {
42+
return path.join(homedir(), pathValue.slice(2));
43+
}
3744
if (path.isAbsolute(pathValue)) {
3845
return pathValue;
3946
}

src/utils/project-config.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import path from 'node:path';
2+
import { homedir } from 'node:os';
23
import { fileURLToPath } from 'node:url';
34
import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
45
import type { FileSystemExecutor } from './FileSystemExecutor.ts';
@@ -125,6 +126,14 @@ function normalizePathValue(value: string, cwd: string): string {
125126
return fileUrlPath;
126127
}
127128

129+
if (value === '~') {
130+
return homedir();
131+
}
132+
133+
if (value.startsWith('~/')) {
134+
return path.join(homedir(), value.slice(2));
135+
}
136+
128137
if (path.isAbsolute(value)) {
129138
return value;
130139
}

0 commit comments

Comments
 (0)