From c4e4d071faf1038ef2f3144dd6f03bf37c145c1f Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 11 Jul 2023 08:12:18 -0700 Subject: [PATCH 01/13] Handle the case where we fail to expand a dir --- aider/commands.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/aider/commands.py b/aider/commands.py index 396c960b08a..60e2022039f 100644 --- a/aider/commands.py +++ b/aider/commands.py @@ -221,7 +221,8 @@ def completions_add(self, partial): yield Completion(fname, start_position=-len(partial)) def glob_filtered_to_repo(self, pattern): - raw_matched_files = Path(self.coder.root).glob(pattern) + raw_matched_files = list(Path(self.coder.root).glob(pattern)) + matched_files = [] for fn in raw_matched_files: matched_files += expand_subdir(fn.relative_to(self.coder.root)) @@ -250,7 +251,10 @@ def cmd_add(self, args): self.io.tool_error(f"No files to add matching pattern: {word}") else: if Path(word).exists(): - matched_files = [word] + if Path(word).is_file(): + matched_files = [word] + else: + self.io.tool_error(f"Unable to add: {word}") elif self.io.confirm_ask( f"No files matched '{word}'. Do you want to create the file?" ): From 7c0ac4d92fddd504ff0a91cc3941f0225e7b17cc Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 11 Jul 2023 08:12:44 -0700 Subject: [PATCH 02/13] Tell git to stop quoting the paths in ls-files --- aider/coders/base_coder.py | 6 +++++- aider/repomap.py | 16 ++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index 2cab25d64c2..39ef5e07dbf 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -964,9 +964,13 @@ def allowed_to_edit(self, path, write_content=None): def get_tracked_files(self): if not self.repo: return [] + + files = self.repo.git.execute(["git", "-c", "core.quotepath=off", "ls-files"]) + files = set(files.splitlines()) + # convert to appropriate os.sep, since git always normalizes to / - files = set(self.repo.git.ls_files().splitlines()) res = set(str(Path(PurePosixPath(path))) for path in files) + return res apply_update_errors = 0 diff --git a/aider/repomap.py b/aider/repomap.py index 6e9f2583465..7535838dcab 100644 --- a/aider/repomap.py +++ b/aider/repomap.py @@ -172,7 +172,10 @@ def split_path(self, path): def run_ctags(self, filename): # Check if the file is in the cache and if the modification time has not changed - file_mtime = os.path.getmtime(filename) + file_mtime = self.get_mtime(filename) + if file_mtime is None: + return [] + cache_key = filename if cache_key in self.TAGS_CACHE and self.TAGS_CACHE[cache_key]["mtime"] == file_mtime: return self.TAGS_CACHE[cache_key]["data"] @@ -239,8 +242,17 @@ def load_ident_cache(self): def save_ident_cache(self): pass + def get_mtime(self, fname): + try: + return os.path.getmtime(fname) + except FileNotFoundError: + self.io.tool_error(f"File not found error: {fname}") + def get_name_identifiers(self, fname, uniq=True): - file_mtime = os.path.getmtime(fname) + file_mtime = self.get_mtime(fname) + if file_mtime is None: + return set() + cache_key = fname if cache_key in self.IDENT_CACHE and self.IDENT_CACHE[cache_key]["mtime"] == file_mtime: idents = self.IDENT_CACHE[cache_key]["data"] From 2f4e20658dc19553523b14846294600c708e8c11 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 11 Jul 2023 08:14:01 -0700 Subject: [PATCH 03/13] fix the test to mock git.execute not git.ls_files --- tests/test_coder.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/test_coder.py b/tests/test_coder.py index c4f95e06f64..a7fc0fc92f1 100644 --- a/tests/test_coder.py +++ b/tests/test_coder.py @@ -30,7 +30,7 @@ def test_check_for_file_mentions(self): # Mock the git repo mock_repo = MagicMock() - mock_repo.git.ls_files.return_value = "file1.txt\nfile2.py" + mock_repo.git.execute.return_value = "file1.txt\nfile2.py" coder.repo = mock_repo # Call the check_for_file_mentions method @@ -77,7 +77,7 @@ def test_check_for_filename_mentions_of_longer_paths(self): # Mock the git repo mock_repo = MagicMock() - mock_repo.git.ls_files.return_value = "file1.txt\nfile2.py" + mock_repo.git.execute.return_value = "file1.txt\nfile2.py" coder.repo = mock_repo # Call the check_for_file_mentions method @@ -104,7 +104,7 @@ def test_check_for_ambiguous_filename_mentions_of_longer_paths(self): # Mock the git repo mock_repo = MagicMock() - mock_repo.git.ls_files.return_value = "file1.txt\nother/file1.txt" + mock_repo.git.execute.return_value = "file1.txt\nother/file1.txt" coder.repo = mock_repo # Call the check_for_file_mentions method @@ -352,7 +352,9 @@ def test_run_with_invalid_request_error(self, mock_chat_completion_create): coder = Coder.create(models.GPT4, None, mock_io, openai_api_key="fake_key") # Set up the mock to raise InvalidRequestError - mock_chat_completion_create.side_effect = openai.error.InvalidRequestError("Invalid request", "param") + mock_chat_completion_create.side_effect = openai.error.InvalidRequestError( + "Invalid request", "param" + ) # Call the run method and assert that InvalidRequestError is raised with self.assertRaises(openai.error.InvalidRequestError): From f1b61d49e93dc563fa4251e0cf92f9ae15fb3161 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 11 Jul 2023 08:18:39 -0700 Subject: [PATCH 04/13] aider: Added a test that creates a temporary directory, initializes a git repository there, adds three empty files, creates a `Coder` object on that directory, and asserts that `coder.get_tracked_files()` returns the three filenames. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Aider chat conversation: USER: make a test which creates a tempdir and inits a git repo there. it should add 3 empty files with the filenames below. the test should create a Coder on that and make sure that coder.get_tracked_files() returns the 3 filenames. Here are the filenames: README.md doc/fänny_dirname/README.md doc/systemüberblick.md ASSISTANT: To create this test, we need to modify the `tests/test_coder.py` file. We will add a new test method named `test_get_tracked_files` in the `TestCoder` class. This method will create a temporary directory, initialize a git repository there, add three empty files, create a `Coder` object on that directory, and assert that `coder.get_tracked_files()` returns the three filenames. Here is the code change: ```python tests/test_coder.py <<<<<<< ORIGINAL if __name__ == "__main__": unittest.main() ======= def test_get_tracked_files(self): # Create a temporary directory tempdir = Path(tempfile.mkdtemp()) # Initialize a git repository in the temporary directory repo = git.Repo.init(tempdir) # Create three empty files and add them to the git repository filenames = ["README.md", "doc/fänny_dirname/README.md", "doc/systemüberblick.md"] for filename in filenames: (tempdir / filename).touch() repo.git.add(filename) # Create a Coder object on the temporary directory coder = Coder.create(models.GPT4, None, io=InputOutput(), openai_api_key="fake_key", root=tempdir) # Assert that coder.get_tracked_files() returns the three filenames self.assertEqual(set(coder.get_tracked_files()), set(filenames)) if __name__ == "__main__": unittest.main() >>>>>>> UPDATED ``` This code assumes that the `Coder` class has a `get_tracked_files` method that returns the filenames of the tracked files in the git repository. If such a method does not exist, it should be implemented in the `Coder` class. --- tests/test_coder.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/test_coder.py b/tests/test_coder.py index a7fc0fc92f1..89b1f32ffc0 100644 --- a/tests/test_coder.py +++ b/tests/test_coder.py @@ -360,5 +360,24 @@ def test_run_with_invalid_request_error(self, mock_chat_completion_create): with self.assertRaises(openai.error.InvalidRequestError): coder.run(with_message="hi") + def test_get_tracked_files(self): + # Create a temporary directory + tempdir = Path(tempfile.mkdtemp()) + + # Initialize a git repository in the temporary directory + repo = git.Repo.init(tempdir) + + # Create three empty files and add them to the git repository + filenames = ["README.md", "doc/fänny_dirname/README.md", "doc/systemüberblick.md"] + for filename in filenames: + (tempdir / filename).touch() + repo.git.add(filename) + + # Create a Coder object on the temporary directory + coder = Coder.create(models.GPT4, None, io=InputOutput(), openai_api_key="fake_key", root=tempdir) + + # Assert that coder.get_tracked_files() returns the three filenames + self.assertEqual(set(coder.get_tracked_files()), set(filenames)) + if __name__ == "__main__": unittest.main() From db8fb97a38dc5c42fb00f9231a8ef5890ee87195 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 11 Jul 2023 08:19:24 -0700 Subject: [PATCH 05/13] added import --- tests/test_coder.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/test_coder.py b/tests/test_coder.py index 89b1f32ffc0..03612ed4fc2 100644 --- a/tests/test_coder.py +++ b/tests/test_coder.py @@ -3,6 +3,7 @@ from pathlib import Path from unittest.mock import MagicMock, patch +import git import openai import requests @@ -374,7 +375,9 @@ def test_get_tracked_files(self): repo.git.add(filename) # Create a Coder object on the temporary directory - coder = Coder.create(models.GPT4, None, io=InputOutput(), openai_api_key="fake_key", root=tempdir) + coder = Coder.create( + models.GPT4, None, io=InputOutput(), openai_api_key="fake_key", root=tempdir + ) # Assert that coder.get_tracked_files() returns the three filenames self.assertEqual(set(coder.get_tracked_files()), set(filenames)) From cb5d2450ecbd6fe60764c1470986848f3ee20643 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 11 Jul 2023 08:20:22 -0700 Subject: [PATCH 06/13] aider: Ensure parent directory exists before creating file in test_get_tracked_files. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Aider chat conversation: USER: I ran this command: pytest -k test_get_tracked_files -s And got this output: ============================= test session starts ============================== platform darwin -- Python 3.11.3, pytest-7.3.1, pluggy-1.0.0 rootdir: /Users/gauthier/Projects/aider configfile: pytest.ini collected 61 items / 60 deselected / 1 selected tests/test_coder.py F =================================== FAILURES =================================== _______________________ TestCoder.test_get_tracked_files _______________________ self = def test_get_tracked_files(self): # Create a temporary directory tempdir = Path(tempfile.mkdtemp()) # Initialize a git repository in the temporary directory repo = git.Repo.init(tempdir) # Create three empty files and add them to the git repository filenames = ["README.md", "doc/fänny_dirname/README.md", "doc/systemüberblick.md"] for filename in filenames: > (tempdir / filename).touch() tests/test_coder.py:374: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = PosixPath('/var/folders/49/kxrdwwbx0h9bchx99397477c0000gn/T/tmpoowegb9x/doc/fänny_dirname/README.md') mode = 438, exist_ok = True def touch(self, mode=0o666, exist_ok=True): """ Create this file with the given access mode, if it doesn't exist. """ if exist_ok: # First try to bump modification time # Implementation note: GNU touch uses the UTIME_NOW option of # the utimensat() / futimens() functions. try: os.utime(self, None) except OSError: # Avoid exception chaining pass else: return flags = os.O_CREAT | os.O_WRONLY if not exist_ok: flags |= os.O_EXCL > fd = os.open(self, flags, mode) E FileNotFoundError: [Errno 2] No such file or directory: '/var/folders/49/kxrdwwbx0h9bchx99397477c0000gn/T/tmpoowegb9x/doc/fänny_dirname/README.md' /usr/local/Cellar/python@3.11/3.11.3/Frameworks/Python.framework/Versions/3.11/lib/python3.11/pathlib.py:1108: FileNotFoundError =========================== short test summary info ============================ FAILED tests/test_coder.py::TestCoder::test_get_tracked_files - FileNotFoundE... ======================= 1 failed, 60 deselected in 1.53s ======================= ASSISTANT: The error message indicates that the directory `doc/fänny_dirname` does not exist when the test tries to create the file `README.md` inside it. We need to ensure that the directory exists before creating the file. We can use the `mkdir` method of `Path` with the `parents=True` argument to create the directory and all its missing parents. Here is the updated code: ```python tests/test_coder.py <<<<<<< ORIGINAL def test_get_tracked_files(self): # Create a temporary directory tempdir = Path(tempfile.mkdtemp()) # Initialize a git repository in the temporary directory repo = git.Repo.init(tempdir) # Create three empty files and add them to the git repository filenames = ["README.md", "doc/fänny_dirname/README.md", "doc/systemüberblick.md"] for filename in filenames: (tempdir / filename).touch() repo.git.add(filename) # Create a Coder object on the temporary directory coder = Coder.create( models.GPT4, None, io=InputOutput(), openai_api_key="fake_key", root=tempdir ) # Assert that coder.get_tracked_files() returns the three filenames self.assertEqual(set(coder.get_tracked_files()), set(filenames)) ======= def test_get_tracked_files(self): # Create a temporary directory tempdir = Path(tempfile.mkdtemp()) # Initialize a git repository in the temporary directory repo = git.Repo.init(tempdir) # Create three empty files and add them to the git repository filenames = ["README.md", "doc/fänny_dirname/README.md", "doc/systemüberblick.md"] for filename in filenames: file_path = tempdir / filename file_path.parent.mkdir(parents=True, exist_ok=True) file_path.touch() repo.git.add(str(file_path)) # Create a Coder object on the temporary directory coder = Coder.create( models.GPT4, None, io=InputOutput(), openai_api_key="fake_key", root=tempdir ) # Assert that coder.get_tracked_files() returns the three filenames self.assertEqual(set(coder.get_tracked_files()), set(filenames)) >>>>>>> UPDATED ``` This code creates the parent directory of each file before creating the file. It also converts the `Path` object to a string before passing it to `repo.git.add`, because the `git` library may not accept `Path` objects. --- tests/test_coder.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_coder.py b/tests/test_coder.py index 03612ed4fc2..9bfc78bfa10 100644 --- a/tests/test_coder.py +++ b/tests/test_coder.py @@ -371,8 +371,10 @@ def test_get_tracked_files(self): # Create three empty files and add them to the git repository filenames = ["README.md", "doc/fänny_dirname/README.md", "doc/systemüberblick.md"] for filename in filenames: - (tempdir / filename).touch() - repo.git.add(filename) + file_path = tempdir / filename + file_path.parent.mkdir(parents=True, exist_ok=True) + file_path.touch() + repo.git.add(str(file_path)) # Create a Coder object on the temporary directory coder = Coder.create( From 59a54f5f833c97c1452d1cd8e0c67eb4903596a2 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 11 Jul 2023 08:21:16 -0700 Subject: [PATCH 07/13] fix Coder.create --- tests/test_coder.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/test_coder.py b/tests/test_coder.py index 9bfc78bfa10..75684074011 100644 --- a/tests/test_coder.py +++ b/tests/test_coder.py @@ -378,7 +378,11 @@ def test_get_tracked_files(self): # Create a Coder object on the temporary directory coder = Coder.create( - models.GPT4, None, io=InputOutput(), openai_api_key="fake_key", root=tempdir + models.GPT4, + None, + io=InputOutput(), + openai_api_key="fake_key", + fnames=[str(tempdir / filenames[0])], ) # Assert that coder.get_tracked_files() returns the three filenames From 73f5fb05e597dcd7bc5b811ae1cf90410cbb9611 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 11 Jul 2023 08:40:30 -0700 Subject: [PATCH 08/13] Make rel_repo_dir robust on windows when cwd and the repo are on different drives --- aider/coders/base_coder.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index 39ef5e07dbf..e304bcdf249 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -160,7 +160,7 @@ def __init__( self.abs_fnames = set([str(Path(fname).resolve()) for fname in fnames]) if self.repo: - rel_repo_dir = os.path.relpath(self.repo.git_dir, os.getcwd()) + rel_repo_dir = self.get_rel_repo_dir() self.io.tool_output(f"Git repo: {rel_repo_dir}") else: self.io.tool_output("Git repo: none") @@ -210,6 +210,12 @@ def find_common_root(self): self.root = utils.safe_abs_path(self.root) + def get_rel_repo_dir(self): + try: + return os.path.relpath(self.repo.git_dir, os.getcwd()) + except ValueError: + return self.repo.git_dir + def add_rel_fname(self, rel_fname): self.abs_fnames.add(self.abs_root_path(rel_fname)) @@ -265,7 +271,7 @@ def set_repo(self, cmd_line_fnames): new_files.append(relative_fname) if new_files: - rel_repo_dir = os.path.relpath(self.repo.git_dir, os.getcwd()) + rel_repo_dir = self.get_rel_repo_dir() self.io.tool_output(f"Files not tracked in {rel_repo_dir}:") for fn in new_files: From 68c26a60efd5073abc2b4642eb0dd8fc38e39793 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 11 Jul 2023 09:08:37 -0700 Subject: [PATCH 09/13] get tracked files by traversing the tree --- aider/coders/base_coder.py | 11 +++++++++-- tests/test_coder.py | 22 +++++++++++----------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index e304bcdf249..c0a16499a46 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -971,8 +971,15 @@ def get_tracked_files(self): if not self.repo: return [] - files = self.repo.git.execute(["git", "-c", "core.quotepath=off", "ls-files"]) - files = set(files.splitlines()) + try: + commit = self.repo.head.commit + except ValueError: + return set() + + files = [] + for blob in commit.tree.traverse(): + if blob.type == "blob": # blob is a file + files.append(blob.path) # convert to appropriate os.sep, since git always normalizes to / res = set(str(Path(PurePosixPath(path))) for path in files) diff --git a/tests/test_coder.py b/tests/test_coder.py index 75684074011..403bf080584 100644 --- a/tests/test_coder.py +++ b/tests/test_coder.py @@ -30,9 +30,9 @@ def test_check_for_file_mentions(self): coder = Coder.create(models.GPT4, None, mock_io, openai_api_key="fake_key") # Mock the git repo - mock_repo = MagicMock() - mock_repo.git.execute.return_value = "file1.txt\nfile2.py" - coder.repo = mock_repo + mock = MagicMock() + mock.return_value = set(["file1.txt", "file2.py"]) + coder.get_tracked_files = mock # Call the check_for_file_mentions method coder.check_for_file_mentions("Please check file1.txt and file2.py") @@ -76,10 +76,9 @@ def test_check_for_filename_mentions_of_longer_paths(self): # Initialize the Coder object with the mocked IO and mocked repo coder = Coder.create(models.GPT4, None, mock_io, openai_api_key="fake_key") - # Mock the git repo - mock_repo = MagicMock() - mock_repo.git.execute.return_value = "file1.txt\nfile2.py" - coder.repo = mock_repo + mock = MagicMock() + mock.return_value = set(["file1.txt", "file2.py"]) + coder.get_tracked_files = mock # Call the check_for_file_mentions method coder.check_for_file_mentions("Please check file1.txt and file2.py") @@ -103,10 +102,9 @@ def test_check_for_ambiguous_filename_mentions_of_longer_paths(self): # Initialize the Coder object with the mocked IO and mocked repo coder = Coder.create(models.GPT4, None, mock_io, openai_api_key="fake_key") - # Mock the git repo - mock_repo = MagicMock() - mock_repo.git.execute.return_value = "file1.txt\nother/file1.txt" - coder.repo = mock_repo + mock = MagicMock() + mock.return_value = set(["file1.txt", "other/file1.txt"]) + coder.get_tracked_files = mock # Call the check_for_file_mentions method coder.check_for_file_mentions("Please check file1.txt!") @@ -376,6 +374,8 @@ def test_get_tracked_files(self): file_path.touch() repo.git.add(str(file_path)) + repo.git.commit("-m", "added") + # Create a Coder object on the temporary directory coder = Coder.create( models.GPT4, From cccd0d1ebe3f1ad6739efa63fd25449baff713fd Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 11 Jul 2023 09:15:21 -0700 Subject: [PATCH 10/13] Make the tests run on windows; added test for files with quotes --- tests/test_coder.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/test_coder.py b/tests/test_coder.py index 403bf080584..9b3b309de76 100644 --- a/tests/test_coder.py +++ b/tests/test_coder.py @@ -1,3 +1,4 @@ +import os import tempfile import unittest from pathlib import Path @@ -367,12 +368,20 @@ def test_get_tracked_files(self): repo = git.Repo.init(tempdir) # Create three empty files and add them to the git repository - filenames = ["README.md", "doc/fänny_dirname/README.md", "doc/systemüberblick.md"] + filenames = ["README.md", "fänny.md", "systemüberblick.md", 'file"with"quotes.txt'] + created_files = [] for filename in filenames: file_path = tempdir / filename - file_path.parent.mkdir(parents=True, exist_ok=True) - file_path.touch() - repo.git.add(str(file_path)) + try: + file_path.touch() + repo.git.add(str(file_path)) + created_files.append(filename) + except OSError: + # windows won't allow files with quotes, that's ok + self.assertIn('"', filename) + self.assertEqual(os.name, "nt") + + self.assertTrue(len(created_files) >= 3) repo.git.commit("-m", "added") @@ -386,7 +395,7 @@ def test_get_tracked_files(self): ) # Assert that coder.get_tracked_files() returns the three filenames - self.assertEqual(set(coder.get_tracked_files()), set(filenames)) + self.assertEqual(set(coder.get_tracked_files()), set(created_files)) if __name__ == "__main__": unittest.main() From 8d5f17898a969f8f57139b97c90c1cc775f38790 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 11 Jul 2023 09:17:55 -0700 Subject: [PATCH 11/13] test subdirs too --- tests/test_coder.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/test_coder.py b/tests/test_coder.py index 9b3b309de76..5aa7255c5c9 100644 --- a/tests/test_coder.py +++ b/tests/test_coder.py @@ -368,14 +368,15 @@ def test_get_tracked_files(self): repo = git.Repo.init(tempdir) # Create three empty files and add them to the git repository - filenames = ["README.md", "fänny.md", "systemüberblick.md", 'file"with"quotes.txt'] + filenames = ["README.md", "subdir/fänny.md", "systemüber/blick.md", 'file"with"quotes.txt'] created_files = [] for filename in filenames: file_path = tempdir / filename try: + file_path.parent.mkdir(parents=True, exist_ok=True) file_path.touch() repo.git.add(str(file_path)) - created_files.append(filename) + created_files.append(Path(filename)) except OSError: # windows won't allow files with quotes, that's ok self.assertIn('"', filename) @@ -394,8 +395,13 @@ def test_get_tracked_files(self): fnames=[str(tempdir / filenames[0])], ) + tracked_files = coder.get_tracked_files() + + # On windows, paths will come back \like\this, so normalize them back to Paths + tracked_files = [Path(fn) for fn in tracked_files] + # Assert that coder.get_tracked_files() returns the three filenames - self.assertEqual(set(coder.get_tracked_files()), set(created_files)) + self.assertEqual(set(tracked_files), set(created_files)) if __name__ == "__main__": unittest.main() From 3e3694b38aaa62f1ec726c12b657e7f9289dd1cb Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 11 Jul 2023 09:20:50 -0700 Subject: [PATCH 12/13] aider: Set the git user name and email in the `get_tracked_files` test. # Aider chat conversation: USER: set the git user name and email in the `get_tracked_files` test ASSISTANT: To set the git user name and email in the `get_tracked_files` test, we need to modify the `tests/test_coder.py` file. We will add two lines of code to set the git user name and email after initializing the git repository. Here is the change: ```python tests/test_coder.py <<<<<<< ORIGINAL # Initialize a git repository in the temporary directory repo = git.Repo.init(tempdir) ======= # Initialize a git repository in the temporary directory and set user name and email repo = git.Repo.init(tempdir) repo.config_writer().set_value("user", "name", "Test User").release() repo.config_writer().set_value("user", "email", "testuser@example.com").release() >>>>>>> UPDATED ``` This change sets the git user name to "Test User" and the email to "testuser@example.com". --- tests/test_coder.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_coder.py b/tests/test_coder.py index 5aa7255c5c9..ea3b62d8627 100644 --- a/tests/test_coder.py +++ b/tests/test_coder.py @@ -364,8 +364,10 @@ def test_get_tracked_files(self): # Create a temporary directory tempdir = Path(tempfile.mkdtemp()) - # Initialize a git repository in the temporary directory + # Initialize a git repository in the temporary directory and set user name and email repo = git.Repo.init(tempdir) + repo.config_writer().set_value("user", "name", "Test User").release() + repo.config_writer().set_value("user", "email", "testuser@example.com").release() # Create three empty files and add them to the git repository filenames = ["README.md", "subdir/fänny.md", "systemüber/blick.md", 'file"with"quotes.txt'] From 3294479c31543f968672d25498e3ee428471aa7f Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Tue, 11 Jul 2023 09:24:45 -0700 Subject: [PATCH 13/13] Updated HISTORY --- HISTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.md b/HISTORY.md index 8b8596486f8..1bc59993fe3 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -4,6 +4,7 @@ - Added `--dark-mode` to select colors suitable for a dark terminal background - Reorganized the `--help` output +- Bugfix and tests around git filenames with unicode characters - Bugfix so that aider throws an exception when OpenAI returns InvalidRequest - Bugfix/improvement to /add and /drop to recurse selected directories - Bugfix for live diff output when using "whole" edit format