From a9fe4532c7ab722c02982a7702fbb502b39c4886 Mon Sep 17 00:00:00 2001 From: Paul Gauthier Date: Sat, 24 Feb 2024 09:38:06 -0800 Subject: [PATCH] Aider should fully ignore files in aiderignore #479 --- aider/coders/base_coder.py | 26 ++++++++++++++++---------- aider/commands.py | 4 ++++ aider/repo.py | 7 +++---- tests/test_coder.py | 28 ++++++++++++++++++++++++++++ tests/test_commands.py | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 83 insertions(+), 14 deletions(-) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index 9b7a1d2a4..10e87c79e 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -156,6 +156,22 @@ class Coder: self.commands = Commands(self.io, self, voice_language) + if use_git: + try: + self.repo = GitRepo( + self.io, fnames, git_dname, aider_ignore_file, client=self.client + ) + self.root = self.repo.root + except FileNotFoundError: + self.repo = None + + if self.repo: + filtered_fnames = self.repo.filter_ignored_files(fnames) + for fname in fnames: + if fname not in filtered_fnames: + self.io.tool_error(f"Skipping {fname} that matches aiderignore spec.") + fnames = filtered_fnames + for fname in fnames: fname = Path(fname) if not fname.exists(): @@ -167,16 +183,6 @@ class Coder: raise ValueError(f"{fname} is not a file") self.abs_fnames.add(str(fname.resolve())) - - if use_git: - try: - self.repo = GitRepo( - self.io, fnames, git_dname, aider_ignore_file, client=self.client - ) - self.root = self.repo.root - except FileNotFoundError: - self.repo = None - if self.repo: rel_repo_dir = self.repo.get_rel_repo_dir() num_files = len(self.repo.get_tracked_files()) diff --git a/aider/commands.py b/aider/commands.py index 4877fefbc..4c723a193 100644 --- a/aider/commands.py +++ b/aider/commands.py @@ -342,6 +342,10 @@ class Commands: else: fname = Path(self.coder.root) / word + if self.coder.repo and not self.coder.repo.filter_ignored_files([fname]): + self.io.tool_error(f"Skipping {fname} that matches aiderignore spec.") + continue + if fname.exists() and fname.is_file(): all_matched_files.add(str(fname)) continue diff --git a/aider/repo.py b/aider/repo.py index c5ba46172..d7332d0bc 100644 --- a/aider/repo.py +++ b/aider/repo.py @@ -41,6 +41,8 @@ class GitRepo: repo_paths.append(repo_path) except git.exc.InvalidGitRepositoryError: pass + except git.exc.NoSuchPathError: + pass num_repos = len(set(repo_paths)) @@ -194,10 +196,7 @@ class GitRepo: files.extend(staged_files) # convert to appropriate os.sep, since git always normalizes to / - res = set( - self.normalize_path(path) - for path in files - ) + res = set(self.normalize_path(path) for path in files) return self.filter_ignored_files(res) diff --git a/tests/test_coder.py b/tests/test_coder.py index ed8a9f102..ff2c7e042 100644 --- a/tests/test_coder.py +++ b/tests/test_coder.py @@ -578,6 +578,34 @@ two diff = saved_diffs[0] self.assertIn("file.txt", diff) + def test_skip_aiderignored_files(self): + with GitTemporaryDirectory(): + repo = git.Repo() + + fname1 = "ignoreme1.txt" + fname2 = "ignoreme2.txt" + fname3 = "dir/ignoreme3.txt" + + Path(fname2).touch() + repo.git.add(str(fname2)) + repo.git.commit("-m", "initial") + + aignore = Path(".aiderignore") + aignore.write_text(f"{fname1}\n{fname2}\ndir\n") + + io = InputOutput(yes=True) + coder = Coder.create( + models.GPT4, + None, + io, + fnames=[fname1, fname2, fname3], + aider_ignore_file=str(aignore), + ) + + self.assertNotIn(fname1, str(coder.abs_fnames)) + self.assertNotIn(fname2, str(coder.abs_fnames)) + self.assertNotIn(fname3, str(coder.abs_fnames)) + if __name__ == "__main__": unittest.main() diff --git a/tests/test_commands.py b/tests/test_commands.py index 0f686acef..7fd24a4f5 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -6,6 +6,7 @@ import tempfile from io import StringIO from pathlib import Path from unittest import TestCase +from unittest.mock import patch import git @@ -23,6 +24,10 @@ class TestCommands(TestCase): self.tempdir = tempfile.mkdtemp() os.chdir(self.tempdir) + self.patcher = patch("aider.coders.base_coder.check_model_availability") + self.mock_check = self.patcher.start() + self.mock_check.return_value = True + def tearDown(self): os.chdir(self.original_cwd) shutil.rmtree(self.tempdir, ignore_errors=True) @@ -537,3 +542,30 @@ class TestCommands(TestCase): del coder del commands del repo + + def test_cmd_add_aiderignored_file(self): + with GitTemporaryDirectory(): + repo = git.Repo() + + fname1 = "ignoreme1.txt" + fname2 = "ignoreme2.txt" + fname3 = "dir/ignoreme3.txt" + + Path(fname2).touch() + repo.git.add(str(fname2)) + repo.git.commit("-m", "initial") + + aignore = Path(".aiderignore") + aignore.write_text(f"{fname1}\n{fname2}\ndir\n") + + io = InputOutput(yes=True) + coder = Coder.create( + models.GPT4, None, io, fnames=[fname1, fname2], aider_ignore_file=str(aignore) + ) + commands = Commands(io, coder) + + commands.cmd_add(f"{fname1} {fname2} {fname3}") + + self.assertNotIn(fname1, str(coder.abs_fnames)) + self.assertNotIn(fname2, str(coder.abs_fnames)) + self.assertNotIn(fname3, str(coder.abs_fnames))