We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
--upgrade-package downgrades unrelated pre-release package when --pre not given
<!-- Describe the issue briefly here. -->

#### Environment Versions

1. OS Type: macOS 10.15.4
1. Python version: 3.7.7
1. pip version:  20.0.2
1. pip-tools version: 4.5.1

#### Steps to replicate

(Note: this example will stop working when `gevent` releases 1.5 final but it can be replicated with any other package that currently has a pre-release version.)

1. Example `req.in` file:
    ```
    click<7
    gevent
    ```
2. `pip-compile req.in`
    Output:
    ```
    #
    # This file is autogenerated by pip-compile
    # To update, run:
    #
    #    pip-compile req.in
    #
    click==6.7                # via -r req.in
    gevent==1.4.0             # via -r req.in
    greenlet==0.4.15          # via gevent
    ```
3. Upgrade gevent to pre-relese
    `pip-compile --pre --upgrade-package gevent req.in`
    Output:
    ```
    #
    # This file is autogenerated by pip-compile
    # To update, run:
    #
    #    pip-compile --pre req.in
    #
    click==6.7                # via -r req.in
    gevent==1.5a4             # via -r req.in
    greenlet==0.4.15          # via gevent
    ```
4. Remove version pin of `click` in `.in` file:
    ```
    click
    gevent
    ```
5. Upgrade click:
    `pip-compile --upgrade-package click req.in`
    Output:
    ```
    #
    # This file is autogenerated by pip-compile
    # To update, run:
    #
    #    pip-compile req.in
    #
    click==6.7                # via -r req.in
    gevent==1.4.0             # via -r req.in
    greenlet==0.4.15          # via gevent
    ```

#### Expected result

Once a package has been resolved to a pre-release version it should never "magically" be downgraded. Especially if only unrelated other packages are concerned.

I could see that there may be an argument for a plain `pip-compile` run to revert to the non-prerelease version, but I would disagree even there. But for `--upgrade-package` I see no way where this is correct behaviour.

#### Actual result

Not giving `--pre` at any time after it has been used once and a package is resolved to a pre-release version will downgrade it back to the last released version.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `piptools/repositories/local.py`
Content:
```
1 # coding: utf-8
2 from __future__ import absolute_import, division, print_function, unicode_literals
3 
4 from contextlib import contextmanager
5 
6 from pip._internal.utils.hashes import FAVORITE_HASH
7 
8 from .._compat import PIP_VERSION
9 from .base import BaseRepository
10 
11 from piptools.utils import as_tuple, key_from_ireq, make_install_requirement
12 
13 
14 def ireq_satisfied_by_existing_pin(ireq, existing_pin):
15     """
16     Return True if the given InstallationRequirement is satisfied by the
17     previously encountered version pin.
18     """
19     version = next(iter(existing_pin.req.specifier)).version
20     return version in ireq.req.specifier
21 
22 
23 class LocalRequirementsRepository(BaseRepository):
24     """
25     The LocalRequirementsRepository proxied the _real_ repository by first
26     checking if a requirement can be satisfied by existing pins (i.e. the
27     result of a previous compile step).
28 
29     In effect, if a requirement can be satisfied with a version pinned in the
30     requirements file, we prefer that version over the best match found in
31     PyPI.  This keeps updates to the requirements.txt down to a minimum.
32     """
33 
34     def __init__(self, existing_pins, proxied_repository):
35         self.repository = proxied_repository
36         self.existing_pins = existing_pins
37 
38     @property
39     def options(self):
40         return self.repository.options
41 
42     @property
43     def finder(self):
44         return self.repository.finder
45 
46     @property
47     def session(self):
48         return self.repository.session
49 
50     @property
51     def DEFAULT_INDEX_URL(self):
52         return self.repository.DEFAULT_INDEX_URL
53 
54     def clear_caches(self):
55         self.repository.clear_caches()
56 
57     def freshen_build_caches(self):
58         self.repository.freshen_build_caches()
59 
60     def find_best_match(self, ireq, prereleases=None):
61         key = key_from_ireq(ireq)
62         existing_pin = self.existing_pins.get(key)
63         if existing_pin and ireq_satisfied_by_existing_pin(ireq, existing_pin):
64             project, version, _ = as_tuple(existing_pin)
65             return make_install_requirement(
66                 project, version, ireq.extras, constraint=ireq.constraint
67             )
68         else:
69             return self.repository.find_best_match(ireq, prereleases)
70 
71     def get_dependencies(self, ireq):
72         return self.repository.get_dependencies(ireq)
73 
74     def get_hashes(self, ireq):
75         key = key_from_ireq(ireq)
76         existing_pin = self.existing_pins.get(key)
77         if existing_pin and ireq_satisfied_by_existing_pin(ireq, existing_pin):
78             if PIP_VERSION[:2] <= (20, 0):
79                 hashes = existing_pin.options.get("hashes", {})
80             else:
81                 hashes = existing_pin.hash_options
82             hexdigests = hashes.get(FAVORITE_HASH)
83             if hexdigests:
84                 return {
85                     ":".join([FAVORITE_HASH, hexdigest]) for hexdigest in hexdigests
86                 }
87         return self.repository.get_hashes(ireq)
88 
89     @contextmanager
90     def allow_all_wheels(self):
91         with self.repository.allow_all_wheels():
92             yield
93
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/piptools/repositories/local.py b/piptools/repositories/local.py
--- a/piptools/repositories/local.py
+++ b/piptools/repositories/local.py
@@ -17,7 +17,9 @@
     previously encountered version pin.
     """
     version = next(iter(existing_pin.req.specifier)).version
-    return version in ireq.req.specifier
+    return ireq.req.specifier.contains(
+        version, prereleases=existing_pin.req.specifier.prereleases
+    )
 
 
 class LocalRequirementsRepository(BaseRepository):

{"golden_diff": "diff --git a/piptools/repositories/local.py b/piptools/repositories/local.py\n--- a/piptools/repositories/local.py\n+++ b/piptools/repositories/local.py\n@@ -17,7 +17,9 @@\n     previously encountered version pin.\n     \"\"\"\n     version = next(iter(existing_pin.req.specifier)).version\n-    return version in ireq.req.specifier\n+    return ireq.req.specifier.contains(\n+        version, prereleases=existing_pin.req.specifier.prereleases\n+    )\n \n \n class LocalRequirementsRepository(BaseRepository):\n", "issue": "--upgrade-package downgrades unrelated pre-release package when --pre not given\n<!-- Describe the issue briefly here. -->\r\n\r\n#### Environment Versions\r\n\r\n1. OS Type: macOS 10.15.4\r\n1. Python version: 3.7.7\r\n1. pip version:  20.0.2\r\n1. pip-tools version: 4.5.1\r\n\r\n#### Steps to replicate\r\n\r\n(Note: this example will stop working when `gevent` releases 1.5 final but it can be replicated with any other package that currently has a pre-release version.)\r\n\r\n1. Example `req.in` file:\r\n    ```\r\n    click<7\r\n    gevent\r\n    ```\r\n2. `pip-compile req.in`\r\n    Output:\r\n    ```\r\n    #\r\n    # This file is autogenerated by pip-compile\r\n    # To update, run:\r\n    #\r\n    #    pip-compile req.in\r\n    #\r\n    click==6.7                # via -r req.in\r\n    gevent==1.4.0             # via -r req.in\r\n    greenlet==0.4.15          # via gevent\r\n    ```\r\n3. Upgrade gevent to pre-relese\r\n    `pip-compile --pre --upgrade-package gevent req.in`\r\n    Output:\r\n    ```\r\n    #\r\n    # This file is autogenerated by pip-compile\r\n    # To update, run:\r\n    #\r\n    #    pip-compile --pre req.in\r\n    #\r\n    click==6.7                # via -r req.in\r\n    gevent==1.5a4             # via -r req.in\r\n    greenlet==0.4.15          # via gevent\r\n    ```\r\n4. Remove version pin of `click` in `.in` file:\r\n    ```\r\n    click\r\n    gevent\r\n    ```\r\n5. Upgrade click:\r\n    `pip-compile --upgrade-package click req.in`\r\n    Output:\r\n    ```\r\n    #\r\n    # This file is autogenerated by pip-compile\r\n    # To update, run:\r\n    #\r\n    #    pip-compile req.in\r\n    #\r\n    click==6.7                # via -r req.in\r\n    gevent==1.4.0             # via -r req.in\r\n    greenlet==0.4.15          # via gevent\r\n    ```\r\n\r\n#### Expected result\r\n\r\nOnce a package has been resolved to a pre-release version it should never \"magically\" be downgraded. Especially if only unrelated other packages are concerned.\r\n\r\nI could see that there may be an argument for a plain `pip-compile` run to revert to the non-prerelease version, but I would disagree even there. But for `--upgrade-package` I see no way where this is correct behaviour.\r\n\r\n#### Actual result\r\n\r\nNot giving `--pre` at any time after it has been used once and a package is resolved to a pre-release version will downgrade it back to the last released version.\n", "before_files": [{"content": "# coding: utf-8\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nfrom contextlib import contextmanager\n\nfrom pip._internal.utils.hashes import FAVORITE_HASH\n\nfrom .._compat import PIP_VERSION\nfrom .base import BaseRepository\n\nfrom piptools.utils import as_tuple, key_from_ireq, make_install_requirement\n\n\ndef ireq_satisfied_by_existing_pin(ireq, existing_pin):\n    \"\"\"\n    Return True if the given InstallationRequirement is satisfied by the\n    previously encountered version pin.\n    \"\"\"\n    version = next(iter(existing_pin.req.specifier)).version\n    return version in ireq.req.specifier\n\n\nclass LocalRequirementsRepository(BaseRepository):\n    \"\"\"\n    The LocalRequirementsRepository proxied the _real_ repository by first\n    checking if a requirement can be satisfied by existing pins (i.e. the\n    result of a previous compile step).\n\n    In effect, if a requirement can be satisfied with a version pinned in the\n    requirements file, we prefer that version over the best match found in\n    PyPI.  This keeps updates to the requirements.txt down to a minimum.\n    \"\"\"\n\n    def __init__(self, existing_pins, proxied_repository):\n        self.repository = proxied_repository\n        self.existing_pins = existing_pins\n\n    @property\n    def options(self):\n        return self.repository.options\n\n    @property\n    def finder(self):\n        return self.repository.finder\n\n    @property\n    def session(self):\n        return self.repository.session\n\n    @property\n    def DEFAULT_INDEX_URL(self):\n        return self.repository.DEFAULT_INDEX_URL\n\n    def clear_caches(self):\n        self.repository.clear_caches()\n\n    def freshen_build_caches(self):\n        self.repository.freshen_build_caches()\n\n    def find_best_match(self, ireq, prereleases=None):\n        key = key_from_ireq(ireq)\n        existing_pin = self.existing_pins.get(key)\n        if existing_pin and ireq_satisfied_by_existing_pin(ireq, existing_pin):\n            project, version, _ = as_tuple(existing_pin)\n            return make_install_requirement(\n                project, version, ireq.extras, constraint=ireq.constraint\n            )\n        else:\n            return self.repository.find_best_match(ireq, prereleases)\n\n    def get_dependencies(self, ireq):\n        return self.repository.get_dependencies(ireq)\n\n    def get_hashes(self, ireq):\n        key = key_from_ireq(ireq)\n        existing_pin = self.existing_pins.get(key)\n        if existing_pin and ireq_satisfied_by_existing_pin(ireq, existing_pin):\n            if PIP_VERSION[:2] <= (20, 0):\n                hashes = existing_pin.options.get(\"hashes\", {})\n            else:\n                hashes = existing_pin.hash_options\n            hexdigests = hashes.get(FAVORITE_HASH)\n            if hexdigests:\n                return {\n                    \":\".join([FAVORITE_HASH, hexdigest]) for hexdigest in hexdigests\n                }\n        return self.repository.get_hashes(ireq)\n\n    @contextmanager\n    def allow_all_wheels(self):\n        with self.repository.allow_all_wheels():\n            yield\n", "path": "piptools/repositories/local.py"}], "after_files": [{"content": "# coding: utf-8\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nfrom contextlib import contextmanager\n\nfrom pip._internal.utils.hashes import FAVORITE_HASH\n\nfrom .._compat import PIP_VERSION\nfrom .base import BaseRepository\n\nfrom piptools.utils import as_tuple, key_from_ireq, make_install_requirement\n\n\ndef ireq_satisfied_by_existing_pin(ireq, existing_pin):\n    \"\"\"\n    Return True if the given InstallationRequirement is satisfied by the\n    previously encountered version pin.\n    \"\"\"\n    version = next(iter(existing_pin.req.specifier)).version\n    return ireq.req.specifier.contains(\n        version, prereleases=existing_pin.req.specifier.prereleases\n    )\n\n\nclass LocalRequirementsRepository(BaseRepository):\n    \"\"\"\n    The LocalRequirementsRepository proxied the _real_ repository by first\n    checking if a requirement can be satisfied by existing pins (i.e. the\n    result of a previous compile step).\n\n    In effect, if a requirement can be satisfied with a version pinned in the\n    requirements file, we prefer that version over the best match found in\n    PyPI.  This keeps updates to the requirements.txt down to a minimum.\n    \"\"\"\n\n    def __init__(self, existing_pins, proxied_repository):\n        self.repository = proxied_repository\n        self.existing_pins = existing_pins\n\n    @property\n    def options(self):\n        return self.repository.options\n\n    @property\n    def finder(self):\n        return self.repository.finder\n\n    @property\n    def session(self):\n        return self.repository.session\n\n    @property\n    def DEFAULT_INDEX_URL(self):\n        return self.repository.DEFAULT_INDEX_URL\n\n    def clear_caches(self):\n        self.repository.clear_caches()\n\n    def freshen_build_caches(self):\n        self.repository.freshen_build_caches()\n\n    def find_best_match(self, ireq, prereleases=None):\n        key = key_from_ireq(ireq)\n        existing_pin = self.existing_pins.get(key)\n        if existing_pin and ireq_satisfied_by_existing_pin(ireq, existing_pin):\n            project, version, _ = as_tuple(existing_pin)\n            return make_install_requirement(\n                project, version, ireq.extras, constraint=ireq.constraint\n            )\n        else:\n            return self.repository.find_best_match(ireq, prereleases)\n\n    def get_dependencies(self, ireq):\n        return self.repository.get_dependencies(ireq)\n\n    def get_hashes(self, ireq):\n        key = key_from_ireq(ireq)\n        existing_pin = self.existing_pins.get(key)\n        if existing_pin and ireq_satisfied_by_existing_pin(ireq, existing_pin):\n            if PIP_VERSION[:2] <= (20, 0):\n                hashes = existing_pin.options.get(\"hashes\", {})\n            else:\n                hashes = existing_pin.hash_options\n            hexdigests = hashes.get(FAVORITE_HASH)\n            if hexdigests:\n                return {\n                    \":\".join([FAVORITE_HASH, hexdigest]) for hexdigest in hexdigests\n                }\n        return self.repository.get_hashes(ireq)\n\n    @contextmanager\n    def allow_all_wheels(self):\n        with self.repository.allow_all_wheels():\n            yield\n", "path": "piptools/repositories/local.py"}]}