# coding: utf-8
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

from piptools.utils import key_from_req
from .base import BaseRepository


def ireq_satisfied_by_existing_pin(ireq, existing_pin):
    """
    Return True if the given InstallationRequirement is satisfied by the
    previously encountered version pin.
    """
    if hasattr(existing_pin.req, 'specs'):
        # pip < 8.1.2
        version = existing_pin.req.specs[0][1]
        return version in ireq.req
    else:
        # pip >= 8.1.2
        version = next(iter(existing_pin.req.specifier)).version
        return version in ireq.req.specifier


class LocalRequirementsRepository(BaseRepository):
    """
    The LocalRequirementsRepository proxied the _real_ repository by first
    checking if a requirement can be satisfied by existing pins (i.e. the
    result of a previous compile step).

    In effect, if a requirement can be satisfied with a version pinned in the
    requirements file, we prefer that version over the best match found in
    PyPI.  This keeps updates to the requirements.txt down to a minimum.
    """
    def __init__(self, existing_pins, proxied_repository):
        self.repository = proxied_repository
        self.existing_pins = existing_pins

    @property
    def finder(self):
        return self.repository.finder

    @property
    def session(self):
        return self.repository.session

    @property
    def DEFAULT_INDEX_URL(self):
        return self.repository.DEFAULT_INDEX_URL

    def clear_caches(self):
        self.repository.clear_caches()

    def freshen_build_caches(self):
        self.repository.freshen_build_caches()

    def find_best_match(self, ireq, prereleases=None):
        key = key_from_req(ireq.req)
        existing_pin = self.existing_pins.get(key)
        if existing_pin and ireq_satisfied_by_existing_pin(ireq, existing_pin):
            return existing_pin
        else:
            return self.repository.find_best_match(ireq, prereleases)

    def get_dependencies(self, ireq):
        return self.repository.get_dependencies(ireq)

@@ -145,16 +145,26 @@
 s import
+ as_tuple,
  key_fro
@@ -168,16 +168,42 @@
 from_req
+, make_install_requirement
 %0Afrom .b
@@ -1978,27 +1978,157 @@
     
-return existing_pin
+project, version, _ = as_tuple(existing_pin)%0A            return make_install_requirement(%0A                project, version, ireq.extras%0A            )
 %0A   

Update LocalRequirementsRepository to retain extras when returning best match.