Skip to content

Commit 8e9ce3f

Browse files
authored
Fix extension env dir loading issue (#20198)
1 parent 812794a commit 8e9ce3f

2 files changed

Lines changed: 67 additions & 3 deletions

File tree

packages/cli/src/config/extensions/extensionSettings.test.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,29 @@ describe('extensionSettings', () => {
590590
SENSITIVE_VAR: 'workspace-secret',
591591
});
592592
});
593+
594+
it('should ignore .env if it is a directory', async () => {
595+
const workspaceEnvPath = path.join(
596+
tempWorkspaceDir,
597+
EXTENSION_SETTINGS_FILENAME,
598+
);
599+
fs.mkdirSync(workspaceEnvPath);
600+
const workspaceKeychain = new KeychainTokenStorage(
601+
`Gemini CLI Extensions test-ext 12345 ${tempWorkspaceDir}`,
602+
);
603+
await workspaceKeychain.setSecret('SENSITIVE_VAR', 'workspace-secret');
604+
605+
const contents = await getScopedEnvContents(
606+
config,
607+
extensionId,
608+
ExtensionSettingScope.WORKSPACE,
609+
tempWorkspaceDir,
610+
);
611+
612+
expect(contents).toEqual({
613+
SENSITIVE_VAR: 'workspace-secret',
614+
});
615+
});
593616
});
594617

595618
describe('getEnvContents (merged)', () => {
@@ -696,6 +719,26 @@ describe('extensionSettings', () => {
696719
expect(actualContent).toContain('VAR1=new-workspace-value');
697720
});
698721

722+
it('should throw an error when trying to write to a workspace with a .env directory', async () => {
723+
const workspaceEnvPath = path.join(tempWorkspaceDir, '.env');
724+
fs.mkdirSync(workspaceEnvPath);
725+
726+
mockRequestSetting.mockResolvedValue('new-workspace-value');
727+
728+
await expect(
729+
updateSetting(
730+
config,
731+
'12345',
732+
'VAR1',
733+
mockRequestSetting,
734+
ExtensionSettingScope.WORKSPACE,
735+
tempWorkspaceDir,
736+
),
737+
).rejects.toThrow(
738+
/Cannot write extension settings to .* because it is a directory./,
739+
);
740+
});
741+
699742
it('should update a sensitive setting in USER scope', async () => {
700743
mockRequestSetting.mockResolvedValue('new-value2');
701744

packages/cli/src/config/extensions/extensionSettings.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,15 @@ export async function maybePromptForSettings(
124124

125125
const envContent = formatEnvContent(nonSensitiveSettings);
126126

127+
if (fsSync.existsSync(envFilePath)) {
128+
const stat = fsSync.statSync(envFilePath);
129+
if (stat.isDirectory()) {
130+
throw new Error(
131+
`Cannot write extension settings to ${envFilePath} because it is a directory.`,
132+
);
133+
}
134+
}
135+
127136
await fs.writeFile(envFilePath, envContent);
128137
}
129138

@@ -173,8 +182,11 @@ export async function getScopedEnvContents(
173182
const envFilePath = getEnvFilePath(extensionName, scope, workspaceDir);
174183
let customEnv: Record<string, string> = {};
175184
if (fsSync.existsSync(envFilePath)) {
176-
const envFile = fsSync.readFileSync(envFilePath, 'utf-8');
177-
customEnv = dotenv.parse(envFile);
185+
const stat = fsSync.statSync(envFilePath);
186+
if (!stat.isDirectory()) {
187+
const envFile = fsSync.readFileSync(envFilePath, 'utf-8');
188+
customEnv = dotenv.parse(envFile);
189+
}
178190
}
179191

180192
if (extensionConfig.settings) {
@@ -260,6 +272,12 @@ export async function updateSetting(
260272
const envFilePath = getEnvFilePath(extensionName, scope, workspaceDir);
261273
let envContent = '';
262274
if (fsSync.existsSync(envFilePath)) {
275+
const stat = fsSync.statSync(envFilePath);
276+
if (stat.isDirectory()) {
277+
throw new Error(
278+
`Cannot write extension settings to ${envFilePath} because it is a directory.`,
279+
);
280+
}
263281
envContent = await fs.readFile(envFilePath, 'utf-8');
264282
}
265283

@@ -324,7 +342,10 @@ async function clearSettings(
324342
keychain: KeychainTokenStorage,
325343
) {
326344
if (fsSync.existsSync(envFilePath)) {
327-
await fs.writeFile(envFilePath, '');
345+
const stat = fsSync.statSync(envFilePath);
346+
if (!stat.isDirectory()) {
347+
await fs.writeFile(envFilePath, '');
348+
}
328349
}
329350
if (!(await keychain.isAvailable())) {
330351
return;

0 commit comments

Comments
 (0)