Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tell git not to quote filenames in ls-files, to handle unicode filenames #85

Merged
merged 14 commits into from
Jul 11, 2023

Conversation

paul-gauthier
Copy link
Owner

Also armors the code in various places to deal with unexpected failures to find/read files.

This should resolve issue #82.

Paul Gauthier added 14 commits July 11, 2023 08:12
… 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.

# 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.
…t_tracked_files.

# 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 = <tests.test_coder.TestCoder testMethod=test_get_tracked_files>

    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/[email protected]/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.
# 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", "[email protected]").release()
>>>>>>> UPDATED
```

This change sets the git user name to "Test User" and the email to "[email protected]".
@paul-gauthier paul-gauthier merged commit 36625ab into main Jul 11, 2023
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant