Repository: mitmproxy/mitmproxy

Issue:
Version detection mistakes an unrelated parent git repository as its own
#### Problem Description
I use <https://github.com/pyenv/pyenv> for Python version and venv management. It's generally installed as a `git clone` and keeps the actual installations and venvs in some deep directories beneath itself. So in a typical setup, you will have a clone of pyenv's repository in `~/.pyenv`, and then if you install mitmproxy in some venv managed by pyenv, its files end up in e.g. `~/.pyenv/versions/3.8.2/envs/mitmproxy/lib/python3.8/site-packages/mitmproxy/`. Because mitmproxy's version detection uses `git describe` and some parent of this directory (namely, `~/.pyenv`) is indeed a git repository, it thinks that this is a dev installation and includes that information in its version output if appropriate, i.e. if there were commits since the last tag in that repo.

#### Steps to reproduce the behavior:
Any git repository higher in the hierarchy than where mitmproxy's files are located would work, but a typical pyenv setup can be reproduced as follows:

1. Install pyenv at some commit that is not tagged. The example below is based on https://github.com/pyenv/pyenv/commit/a8ca63fcc0d6b470e2d5fc18fb85fad90efd4a59, which is two commits ahead of the previous tag v1.2.17. Further, install at least one Python version (I'll assume 3.8.2 below). The installation can be somewhat complicated as various dependencies are required for compiling Python, so I shall not give details about that here. [Here](https://github.com/pyenv/pyenv#installation)'s the starting point for instructions.
2. Install [pyenv-virtualenv](https://github.com/pyenv/pyenv-virtualenv) for virtual environment management; I believe this step is optional for this particular issue, but it greatly simplifies things when using pyenv normally and is a common setup.
3. Install mitmproxy in pyenv: `pyenv virtualenv 3.8.2 mitmproxy && pyenv shell mitmproxy && pip install mitmproxy`
4.
```
$ mitmproxy --version
Mitmproxy: 5.1.1 (+2, commit a8ca63f)
```

I have not tried it, but it should be possible to reproduce the same issue by installing mitmproxy in a venv in a directory that is somewhere beneath a git repository.

#### Possible solution
The `GIT_CEILING_DIRECTORIES` environment variable can be used to limit how far up the directory tree `git` will recurse. For example,

    GIT_CEILING_DIRECTORIES="$(cd .. && pwd)" git describe

would not recurse past the parent directory when attempting to find a git repository. Note that this has to contain absolute paths, so `GIT_CEILING_DIRECTORIES=../..` or similar will not work.

However, even with the strictest `GIT_CEILING_DIRECTORIES` value imaginable, this still doesn't cover the case where the mitmproxy directory is directly inside some unrelated repository (e.g. if someone were to version-control their `site-packages` directory), since that's the structure used in the actual mitmproxy repository.

#### System Information
```
$ mitmproxy --version
Mitmproxy: 5.1.1 (+2, commit a8ca63f)
Python:    3.8.2
OpenSSL:   OpenSSL 1.1.1g  21 Apr 2020
Platform:  Linux-5.6.0-1-amd64-x86_64-with-glibc2.29
```


Discussion:
Thanks for the detailed report. I guess we could run 
```
git cat-file -t cb0e3287090786fad566feb67ac07b8ef361b2c3
```
to check if we are in the right repo.
Ah, clever. Yes, that should work reliably.

Resolving patch:
diff --git a/mitmproxy/version.py b/mitmproxy/version.py
--- a/mitmproxy/version.py
+++ b/mitmproxy/version.py
@@ -20,6 +20,13 @@ def get_dev_version() -> str:
 
     here = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
     try:
+        # Check that we're in the mitmproxy repository: https://github.com/mitmproxy/mitmproxy/issues/3987
+        subprocess.run(
+            ['git', 'cat-file', '-t', 'cb0e3287090786fad566feb67ac07b8ef361b2c3'],
+            stdout=subprocess.DEVNULL,
+            stderr=subprocess.DEVNULL,
+            cwd=here,
+            check=True)
         git_describe = subprocess.check_output(
             ['git', 'describe', '--tags', '--long'],
             stderr=subprocess.STDOUT,


Test patch: