Skip to content

BrokenPipeError on KeyboardInterrupt #427

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

Open
mallamanis opened this issue May 6, 2016 · 2 comments
Open

BrokenPipeError on KeyboardInterrupt #427

mallamanis opened this issue May 6, 2016 · 2 comments

Comments

@mallamanis
Copy link

I am using the latest GitPython on pip and I have bumped into a weird behavior, that seems to be buggy. I have replicated the behavior both with Python 2.7 and 3.4 and has emerged after updating to newer versions of GitPython. Consider the following snippet (assumes a git repository on the current directory):

import time
from git import Repo, TagReference

repository = Repo('.')
current_commit = repository.head.commit
tag_object = TagReference.create(repository, 'test', message='msg')

try:
    for i in range(10):
        time.sleep(1)

except KeyboardInterrupt:
    print("Interrupted. Exiting gracefully...")

data = tag_object.tag.message

If you interrupt (Ctrl+C) the loop, then the last statement fails with a broken pipe exception (full stack trace below). If the code is not interrupted everything succeeds. Also removing the current_commit = repository.head.commit line, makes the problem go away, even if you interrupt a loop.

I presume that it has to do with the handling of the SIGTERM emitted with a Ctrl+C, but I am not sure if this is true.

The stack trace:

Traceback (most recent call last):
  File "./bugreplicate.py", line 15, in <module>
    data = tag_object.tag.message
  File "/usr/local/lib/python2.7/dist-packages/git/refs/tag.py", line 40, in tag
    obj = self.object
  File "/usr/local/lib/python2.7/dist-packages/git/refs/symbolic.py", line 176, in _get_object
    return Object.new_from_sha(self.repo, hex_to_bin(self.dereference_recursive(self.repo, self.path)))
  File "/usr/local/lib/python2.7/dist-packages/git/objects/base.py", line 65, in new_from_sha
    oinfo = repo.odb.info(sha1)
  File "/usr/local/lib/python2.7/dist-packages/git/db.py", line 40, in info
    hexsha, typename, size = self._git.get_object_header(bin_to_hex(sha))
  File "/usr/local/lib/python2.7/dist-packages/git/cmd.py", line 984, in get_object_header
    return self.__get_object_header(cmd, ref)
  File "/usr/local/lib/python2.7/dist-packages/git/cmd.py", line 972, in __get_object_header
    cmd.stdin.flush()
IOError: [Errno 32] Broken pipe

Some more context: I am using GitPython for experimenter link and need a way to handle KeyboardInterruptions. When a Ctrl+C is pressed, I want to be able to safely store data into the git repository.

@Byron Byron self-assigned this May 19, 2016
@Byron
Copy link
Member

Byron commented May 19, 2016

Thanks for the report ! I was able to reproduce the issue, and also found a workaround for now. What you can do is to use a different object database implementation when instantiating the repo like so:

repository = Repo('.', odbt=git.GitDB)

The default object database implementation changed between the versions of gitpython, from the one you see above (pure python) to one that uses a long-running git subprocess to stream objects. The latter is faster and generally preferred, but apparently interacts badly with certain signals.

As GitPython is in maintenance mode and has no functional test suite just yet (which I would need to test these interaction to find a fix), I will leave this one open hoping that others with a similar issue find it (and the workaround).

@Byron Byron removed their assignment May 19, 2016
@mallamanis
Copy link
Author

I've also found another workaround, where I create a new Repo each time I use it (instead of having a persistent object through the lifetime of my program). Since this is a corner case with reasonable workarounds, I'd be happy to consider this issue closed/de-prioritized. It's up to you of course :)

mateimicu added a commit to mateimicu/auto-tag that referenced this issue Sep 1, 2019
Add a summary of the commits that influenced this tag

Also fix a problem with gitpython implementation,
more information gitpython-developers/GitPython#427
kdrag0n added a commit to kdrag0n/pyrobud that referenced this issue Nov 21, 2019
We'll be using `git diff` soon, which the subprocess-based DB
implementation cannot handle (throws a "Broken pipe" error): gitpython-developers/GitPython#427

Signed-off-by: Danny Lin <danny@kdrag0n.dev>
kdrag0n added a commit to kdrag0n/pyrobud that referenced this issue Nov 21, 2019
We'll be using `git diff` soon, which the subprocess-based DB
implementation cannot handle (throws a "Broken pipe" error): gitpython-developers/GitPython#427

Signed-off-by: Danny Lin <danny@kdrag0n.dev>
paul-gauthier added a commit to Aider-AI/aider that referenced this issue May 19, 2023
# Context:
USER: when printing the git repo name, print it relative to cwd
ASSISTANT: To print the git repo name relative to the current working directory, you can modify the `set_repo` function in the `aider/coder.py` file. Here's the change:

```python
aider/coder.py
<<<<<<< ORIGINAL
        if num_repos == 0:
            self.io.tool_error("Files are not in a git repo.")
            return
        if num_repos > 1:
            self.io.tool_error("Files are in different git repos.")
            return

        # gitpython-developers/GitPython#427
        repo = git.Repo(repo_paths.pop(), odbt=git.GitDB)

        self.root = repo.working_tree_dir

        self.io.tool("Using git repo:", self.repo.git_dir)
=======
        if num_repos == 0:
            self.io.tool_error("Files are not in a git repo.")
            return
        if num_repos > 1:
            self.io.tool_error("Files are in different git repos.")
            return

        # gitpython-developers/GitPython#427
        repo = git.Repo(repo_paths.pop(), odbt=git.GitDB)

        self.root = repo.working_tree_dir

        rel_repo_dir = os.path.relpath(self.repo.git_dir, os.getcwd())
        self.io.tool("Using git repo:", rel_repo_dir)
>>>>>>> UPDATED
```

This change replaces `self.repo.git_dir` with `os.path.relpath(self.repo.git_dir, os.getcwd())` to display the git repo path relative to the current working directory.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants