Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 15 additions & 9 deletions aider/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,16 +374,22 @@ def load_dotenv_files(git_root, dotenv_fname, encoding="utf-8"):
# Remove duplicates if it somehow got included by generate_search_path_list
dotenv_files = list(dict.fromkeys(dotenv_files))

existing_env = os.environ.copy()
loaded = []
for fname in dotenv_files:
try:
if Path(fname).exists():
load_dotenv(fname, override=True, encoding=encoding)
loaded.append(fname)
except OSError as e:
print(f"OSError loading {fname}: {e}")
except Exception as e:
print(f"Error loading {fname}: {e}")
try:
for fname in dotenv_files:
try:
if Path(fname).exists():
load_dotenv(fname, override=True, encoding=encoding)
loaded.append(fname)
except OSError as e:
print(f"OSError loading {fname}: {e}")
except Exception as e:
print(f"Error loading {fname}: {e}")
finally:
# Keep values explicitly provided by the user ahead of dotenv files.
for key, value in existing_env.items():
os.environ[key] = value
return loaded


Expand Down
13 changes: 13 additions & 0 deletions tests/basic/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -1470,6 +1470,19 @@ def test_load_dotenv_files_override(self):
# Restore CWD
os.chdir(original_cwd)

def test_load_dotenv_files_does_not_override_existing_env(self):
with GitTemporaryDirectory() as git_dir:
git_dir = Path(git_dir)
env_file = git_dir / ".env"
env_file.write_text("EXISTING_VAR=file_value\nFILE_ONLY_VAR=file_value\n")

with patch.dict(os.environ, {"EXISTING_VAR": "shell_value"}, clear=False):
with patch("pathlib.Path.home", return_value=git_dir / "fake_home"):
load_dotenv_files(str(git_dir), None)

self.assertEqual(os.environ.get("EXISTING_VAR"), "shell_value")
self.assertEqual(os.environ.get("FILE_ONLY_VAR"), "file_value")

@patch("aider.main.InputOutput")
def test_cache_without_stream_no_warning(self, MockInputOutput):
mock_io_instance = MockInputOutput.return_value
Expand Down