We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
'pip freeze' fails with BadCommand if vcs program is not found
Although mechanisms are in place to catch errors in the get_src_requirement() path, a BadCommand exception reaches the top-level and makes pip unusable if any package is found that has a .git directory and 'git' is not installed (or not in path).

I think this should be caught and a warning displayed in [pip.vcs:get_src_requirement()](https://github.com/pypa/pip/blob/3e7c94e9/pip/vcs/__init__.py#L246) instead, allowing the program to continue.

```
> python -m pip -v freeze
Cannot find command 'git'
Exception information:
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\pip\basecommand.py", line 139, in main
    status = self.run(options, args)
  File "C:\Python27\lib\site-packages\pip\commands\freeze.py", line 73, in run
    req = pip.FrozenRequirement.from_dist(dist, dependency_links, find_tags=find_tags)
  File "C:\Python27\lib\site-packages\pip\__init__.py", line 181, in from_dist
    req = get_src_requirement(dist, location, find_tags)
  File "C:\Python27\lib\site-packages\pip\vcs\__init__.py", line 249, in get_src_requirement
    return version_control().get_src_requirement(dist, location, find_tags)
  File "C:\Python27\lib\site-packages\pip\vcs\git.py", line 155, in get_src_requirement
    repo = self.get_url(location)
  File "C:\Python27\lib\site-packages\pip\vcs\git.py", line 123, in get_url
    [self.cmd, 'config', 'remote.origin.url'],
  File "C:\Python27\lib\site-packages\pip\vcs\__init__.py", line 110, in cmd
    command = find_command(self.name)
  File "C:\Python27\lib\site-packages\pip\util.py", line 107, in find_command
    raise BadCommand('Cannot find command %r' % cmd)
BadCommand: Cannot find command 'git'
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pip/vcs/__init__.py`
Content:
```
1 """Handles all VCS (version control) support"""
2 
3 import os
4 import shutil
5 
6 from pip.compat import urlparse, urllib
7 from pip.log import logger
8 from pip.util import (display_path, backup_dir, find_command,
9                       rmtree, ask_path_exists)
10 
11 
12 __all__ = ['vcs', 'get_src_requirement']
13 
14 
15 class VcsSupport(object):
16     _registry = {}
17     schemes = ['ssh', 'git', 'hg', 'bzr', 'sftp', 'svn']
18 
19     def __init__(self):
20         # Register more schemes with urlparse for various version control
21         # systems
22         urlparse.uses_netloc.extend(self.schemes)
23         # Python >= 2.7.4, 3.3 doesn't have uses_fragment
24         if getattr(urlparse, 'uses_fragment', None):
25             urlparse.uses_fragment.extend(self.schemes)
26         super(VcsSupport, self).__init__()
27 
28     def __iter__(self):
29         return self._registry.__iter__()
30 
31     @property
32     def backends(self):
33         return list(self._registry.values())
34 
35     @property
36     def dirnames(self):
37         return [backend.dirname for backend in self.backends]
38 
39     @property
40     def all_schemes(self):
41         schemes = []
42         for backend in self.backends:
43             schemes.extend(backend.schemes)
44         return schemes
45 
46     def register(self, cls):
47         if not hasattr(cls, 'name'):
48             logger.warn('Cannot register VCS %s' % cls.__name__)
49             return
50         if cls.name not in self._registry:
51             self._registry[cls.name] = cls
52 
53     def unregister(self, cls=None, name=None):
54         if name in self._registry:
55             del self._registry[name]
56         elif cls in self._registry.values():
57             del self._registry[cls.name]
58         else:
59             logger.warn('Cannot unregister because no class or name given')
60 
61     def get_backend_name(self, location):
62         """
63         Return the name of the version control backend if found at given
64         location, e.g. vcs.get_backend_name('/path/to/vcs/checkout')
65         """
66         for vc_type in self._registry.values():
67             path = os.path.join(location, vc_type.dirname)
68             if os.path.exists(path):
69                 return vc_type.name
70         return None
71 
72     def get_backend(self, name):
73         name = name.lower()
74         if name in self._registry:
75             return self._registry[name]
76 
77     def get_backend_from_location(self, location):
78         vc_type = self.get_backend_name(location)
79         if vc_type:
80             return self.get_backend(vc_type)
81         return None
82 
83 
84 vcs = VcsSupport()
85 
86 
87 class VersionControl(object):
88     name = ''
89     dirname = ''
90 
91     def __init__(self, url=None, *args, **kwargs):
92         self.url = url
93         self._cmd = None
94         super(VersionControl, self).__init__(*args, **kwargs)
95 
96     def _filter(self, line):
97         return (logger.INFO, line)
98 
99     def _is_local_repository(self, repo):
100         """
101            posix absolute paths start with os.path.sep,
102            win32 ones ones start with drive (like c:\\folder)
103         """
104         drive, tail = os.path.splitdrive(repo)
105         return repo.startswith(os.path.sep) or drive
106 
107     @property
108     def cmd(self):
109         if self._cmd is not None:
110             return self._cmd
111         command = find_command(self.name)
112         logger.info('Found command %r at %r' % (self.name, command))
113         self._cmd = command
114         return command
115 
116     def get_url_rev(self):
117         """
118         Returns the correct repository URL and revision by parsing the given
119         repository URL
120         """
121         error_message = (
122             "Sorry, '%s' is a malformed VCS url. "
123             "The format is <vcs>+<protocol>://<url>, "
124             "e.g. svn+http://myrepo/svn/MyApp#egg=MyApp"
125         )
126         assert '+' in self.url, error_message % self.url
127         url = self.url.split('+', 1)[1]
128         scheme, netloc, path, query, frag = urlparse.urlsplit(url)
129         rev = None
130         if '@' in path:
131             path, rev = path.rsplit('@', 1)
132         url = urlparse.urlunsplit((scheme, netloc, path, query, ''))
133         return url, rev
134 
135     def get_info(self, location):
136         """
137         Returns (url, revision), where both are strings
138         """
139         assert not location.rstrip('/').endswith(self.dirname), \
140             'Bad directory: %s' % location
141         return self.get_url(location), self.get_revision(location)
142 
143     def normalize_url(self, url):
144         """
145         Normalize a URL for comparison by unquoting it and removing any
146         trailing slash.
147         """
148         return urllib.unquote(url).rstrip('/')
149 
150     def compare_urls(self, url1, url2):
151         """
152         Compare two repo URLs for identity, ignoring incidental differences.
153         """
154         return (self.normalize_url(url1) == self.normalize_url(url2))
155 
156     def obtain(self, dest):
157         """
158         Called when installing or updating an editable package, takes the
159         source path of the checkout.
160         """
161         raise NotImplementedError
162 
163     def switch(self, dest, url, rev_options):
164         """
165         Switch the repo at ``dest`` to point to ``URL``.
166         """
167         raise NotImplemented
168 
169     def update(self, dest, rev_options):
170         """
171         Update an already-existing repo to the given ``rev_options``.
172         """
173         raise NotImplementedError
174 
175     def check_destination(self, dest, url, rev_options, rev_display):
176         """
177         Prepare a location to receive a checkout/clone.
178 
179         Return True if the location is ready for (and requires) a
180         checkout/clone, False otherwise.
181         """
182         checkout = True
183         prompt = False
184         if os.path.exists(dest):
185             checkout = False
186             if os.path.exists(os.path.join(dest, self.dirname)):
187                 existing_url = self.get_url(dest)
188                 if self.compare_urls(existing_url, url):
189                     logger.info('%s in %s exists, and has correct URL (%s)' %
190                                 (self.repo_name.title(), display_path(dest),
191                                  url))
192                     logger.notify('Updating %s %s%s' %
193                                   (display_path(dest), self.repo_name,
194                                    rev_display))
195                     self.update(dest, rev_options)
196                 else:
197                     logger.warn('%s %s in %s exists with URL %s' %
198                                 (self.name, self.repo_name,
199                                  display_path(dest), existing_url))
200                     prompt = ('(s)witch, (i)gnore, (w)ipe, (b)ackup ',
201                               ('s', 'i', 'w', 'b'))
202             else:
203                 logger.warn('Directory %s already exists, '
204                             'and is not a %s %s.' %
205                             (dest, self.name, self.repo_name))
206                 prompt = ('(i)gnore, (w)ipe, (b)ackup ', ('i', 'w', 'b'))
207         if prompt:
208             logger.warn('The plan is to install the %s repository %s' %
209                         (self.name, url))
210             response = ask_path_exists('What to do?  %s' % prompt[0],
211                                        prompt[1])
212 
213             if response == 's':
214                 logger.notify('Switching %s %s to %s%s' %
215                               (self.repo_name, display_path(dest), url,
216                                rev_display))
217                 self.switch(dest, url, rev_options)
218             elif response == 'i':
219                 # do nothing
220                 pass
221             elif response == 'w':
222                 logger.warn('Deleting %s' % display_path(dest))
223                 rmtree(dest)
224                 checkout = True
225             elif response == 'b':
226                 dest_dir = backup_dir(dest)
227                 logger.warn('Backing up %s to %s'
228                             % (display_path(dest), dest_dir))
229                 shutil.move(dest, dest_dir)
230                 checkout = True
231         return checkout
232 
233     def unpack(self, location):
234         if os.path.exists(location):
235             rmtree(location)
236         self.obtain(location)
237 
238     def get_src_requirement(self, dist, location, find_tags=False):
239         raise NotImplementedError
240 
241 
242 def get_src_requirement(dist, location, find_tags):
243     version_control = vcs.get_backend_from_location(location)
244     if version_control:
245         return version_control().get_src_requirement(dist, location, find_tags)
246     logger.warn(
247         'cannot determine version of editable source in %s (is not SVN '
248         'checkout, Git clone, Mercurial clone or Bazaar branch)' % location
249     )
250     return dist.as_requirement()
251
```
--- 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/pip/vcs/__init__.py b/pip/vcs/__init__.py
--- a/pip/vcs/__init__.py
+++ b/pip/vcs/__init__.py
@@ -4,6 +4,7 @@
 import shutil
 
 from pip.compat import urlparse, urllib
+from pip.exceptions import BadCommand
 from pip.log import logger
 from pip.util import (display_path, backup_dir, find_command,
                       rmtree, ask_path_exists)
@@ -242,7 +243,15 @@
 def get_src_requirement(dist, location, find_tags):
     version_control = vcs.get_backend_from_location(location)
     if version_control:
-        return version_control().get_src_requirement(dist, location, find_tags)
+        try:
+            return version_control().get_src_requirement(dist,
+                                                         location,
+                                                         find_tags)
+        except BadCommand:
+            logger.warn('cannot determine version of editable source in %s '
+                        '(%s command not found in path)' % (
+                            location, version_control.name))
+            return dist.as_requirement()
     logger.warn(
         'cannot determine version of editable source in %s (is not SVN '
         'checkout, Git clone, Mercurial clone or Bazaar branch)' % location

{"golden_diff": "diff --git a/pip/vcs/__init__.py b/pip/vcs/__init__.py\n--- a/pip/vcs/__init__.py\n+++ b/pip/vcs/__init__.py\n@@ -4,6 +4,7 @@\n import shutil\n \n from pip.compat import urlparse, urllib\n+from pip.exceptions import BadCommand\n from pip.log import logger\n from pip.util import (display_path, backup_dir, find_command,\n                       rmtree, ask_path_exists)\n@@ -242,7 +243,15 @@\n def get_src_requirement(dist, location, find_tags):\n     version_control = vcs.get_backend_from_location(location)\n     if version_control:\n-        return version_control().get_src_requirement(dist, location, find_tags)\n+        try:\n+            return version_control().get_src_requirement(dist,\n+                                                         location,\n+                                                         find_tags)\n+        except BadCommand:\n+            logger.warn('cannot determine version of editable source in %s '\n+                        '(%s command not found in path)' % (\n+                            location, version_control.name))\n+            return dist.as_requirement()\n     logger.warn(\n         'cannot determine version of editable source in %s (is not SVN '\n         'checkout, Git clone, Mercurial clone or Bazaar branch)' % location\n", "issue": "'pip freeze' fails with BadCommand if vcs program is not found\nAlthough mechanisms are in place to catch errors in the get_src_requirement() path, a BadCommand exception reaches the top-level and makes pip unusable if any package is found that has a .git directory and 'git' is not installed (or not in path).\n\nI think this should be caught and a warning displayed in [pip.vcs:get_src_requirement()](https://github.com/pypa/pip/blob/3e7c94e9/pip/vcs/__init__.py#L246) instead, allowing the program to continue.\n\n```\n> python -m pip -v freeze\nCannot find command 'git'\nException information:\nTraceback (most recent call last):\n  File \"C:\\Python27\\lib\\site-packages\\pip\\basecommand.py\", line 139, in main\n    status = self.run(options, args)\n  File \"C:\\Python27\\lib\\site-packages\\pip\\commands\\freeze.py\", line 73, in run\n    req = pip.FrozenRequirement.from_dist(dist, dependency_links, find_tags=find_tags)\n  File \"C:\\Python27\\lib\\site-packages\\pip\\__init__.py\", line 181, in from_dist\n    req = get_src_requirement(dist, location, find_tags)\n  File \"C:\\Python27\\lib\\site-packages\\pip\\vcs\\__init__.py\", line 249, in get_src_requirement\n    return version_control().get_src_requirement(dist, location, find_tags)\n  File \"C:\\Python27\\lib\\site-packages\\pip\\vcs\\git.py\", line 155, in get_src_requirement\n    repo = self.get_url(location)\n  File \"C:\\Python27\\lib\\site-packages\\pip\\vcs\\git.py\", line 123, in get_url\n    [self.cmd, 'config', 'remote.origin.url'],\n  File \"C:\\Python27\\lib\\site-packages\\pip\\vcs\\__init__.py\", line 110, in cmd\n    command = find_command(self.name)\n  File \"C:\\Python27\\lib\\site-packages\\pip\\util.py\", line 107, in find_command\n    raise BadCommand('Cannot find command %r' % cmd)\nBadCommand: Cannot find command 'git'\n```\n\n", "before_files": [{"content": "\"\"\"Handles all VCS (version control) support\"\"\"\n\nimport os\nimport shutil\n\nfrom pip.compat import urlparse, urllib\nfrom pip.log import logger\nfrom pip.util import (display_path, backup_dir, find_command,\n                      rmtree, ask_path_exists)\n\n\n__all__ = ['vcs', 'get_src_requirement']\n\n\nclass VcsSupport(object):\n    _registry = {}\n    schemes = ['ssh', 'git', 'hg', 'bzr', 'sftp', 'svn']\n\n    def __init__(self):\n        # Register more schemes with urlparse for various version control\n        # systems\n        urlparse.uses_netloc.extend(self.schemes)\n        # Python >= 2.7.4, 3.3 doesn't have uses_fragment\n        if getattr(urlparse, 'uses_fragment', None):\n            urlparse.uses_fragment.extend(self.schemes)\n        super(VcsSupport, self).__init__()\n\n    def __iter__(self):\n        return self._registry.__iter__()\n\n    @property\n    def backends(self):\n        return list(self._registry.values())\n\n    @property\n    def dirnames(self):\n        return [backend.dirname for backend in self.backends]\n\n    @property\n    def all_schemes(self):\n        schemes = []\n        for backend in self.backends:\n            schemes.extend(backend.schemes)\n        return schemes\n\n    def register(self, cls):\n        if not hasattr(cls, 'name'):\n            logger.warn('Cannot register VCS %s' % cls.__name__)\n            return\n        if cls.name not in self._registry:\n            self._registry[cls.name] = cls\n\n    def unregister(self, cls=None, name=None):\n        if name in self._registry:\n            del self._registry[name]\n        elif cls in self._registry.values():\n            del self._registry[cls.name]\n        else:\n            logger.warn('Cannot unregister because no class or name given')\n\n    def get_backend_name(self, location):\n        \"\"\"\n        Return the name of the version control backend if found at given\n        location, e.g. vcs.get_backend_name('/path/to/vcs/checkout')\n        \"\"\"\n        for vc_type in self._registry.values():\n            path = os.path.join(location, vc_type.dirname)\n            if os.path.exists(path):\n                return vc_type.name\n        return None\n\n    def get_backend(self, name):\n        name = name.lower()\n        if name in self._registry:\n            return self._registry[name]\n\n    def get_backend_from_location(self, location):\n        vc_type = self.get_backend_name(location)\n        if vc_type:\n            return self.get_backend(vc_type)\n        return None\n\n\nvcs = VcsSupport()\n\n\nclass VersionControl(object):\n    name = ''\n    dirname = ''\n\n    def __init__(self, url=None, *args, **kwargs):\n        self.url = url\n        self._cmd = None\n        super(VersionControl, self).__init__(*args, **kwargs)\n\n    def _filter(self, line):\n        return (logger.INFO, line)\n\n    def _is_local_repository(self, repo):\n        \"\"\"\n           posix absolute paths start with os.path.sep,\n           win32 ones ones start with drive (like c:\\\\folder)\n        \"\"\"\n        drive, tail = os.path.splitdrive(repo)\n        return repo.startswith(os.path.sep) or drive\n\n    @property\n    def cmd(self):\n        if self._cmd is not None:\n            return self._cmd\n        command = find_command(self.name)\n        logger.info('Found command %r at %r' % (self.name, command))\n        self._cmd = command\n        return command\n\n    def get_url_rev(self):\n        \"\"\"\n        Returns the correct repository URL and revision by parsing the given\n        repository URL\n        \"\"\"\n        error_message = (\n            \"Sorry, '%s' is a malformed VCS url. \"\n            \"The format is <vcs>+<protocol>://<url>, \"\n            \"e.g. svn+http://myrepo/svn/MyApp#egg=MyApp\"\n        )\n        assert '+' in self.url, error_message % self.url\n        url = self.url.split('+', 1)[1]\n        scheme, netloc, path, query, frag = urlparse.urlsplit(url)\n        rev = None\n        if '@' in path:\n            path, rev = path.rsplit('@', 1)\n        url = urlparse.urlunsplit((scheme, netloc, path, query, ''))\n        return url, rev\n\n    def get_info(self, location):\n        \"\"\"\n        Returns (url, revision), where both are strings\n        \"\"\"\n        assert not location.rstrip('/').endswith(self.dirname), \\\n            'Bad directory: %s' % location\n        return self.get_url(location), self.get_revision(location)\n\n    def normalize_url(self, url):\n        \"\"\"\n        Normalize a URL for comparison by unquoting it and removing any\n        trailing slash.\n        \"\"\"\n        return urllib.unquote(url).rstrip('/')\n\n    def compare_urls(self, url1, url2):\n        \"\"\"\n        Compare two repo URLs for identity, ignoring incidental differences.\n        \"\"\"\n        return (self.normalize_url(url1) == self.normalize_url(url2))\n\n    def obtain(self, dest):\n        \"\"\"\n        Called when installing or updating an editable package, takes the\n        source path of the checkout.\n        \"\"\"\n        raise NotImplementedError\n\n    def switch(self, dest, url, rev_options):\n        \"\"\"\n        Switch the repo at ``dest`` to point to ``URL``.\n        \"\"\"\n        raise NotImplemented\n\n    def update(self, dest, rev_options):\n        \"\"\"\n        Update an already-existing repo to the given ``rev_options``.\n        \"\"\"\n        raise NotImplementedError\n\n    def check_destination(self, dest, url, rev_options, rev_display):\n        \"\"\"\n        Prepare a location to receive a checkout/clone.\n\n        Return True if the location is ready for (and requires) a\n        checkout/clone, False otherwise.\n        \"\"\"\n        checkout = True\n        prompt = False\n        if os.path.exists(dest):\n            checkout = False\n            if os.path.exists(os.path.join(dest, self.dirname)):\n                existing_url = self.get_url(dest)\n                if self.compare_urls(existing_url, url):\n                    logger.info('%s in %s exists, and has correct URL (%s)' %\n                                (self.repo_name.title(), display_path(dest),\n                                 url))\n                    logger.notify('Updating %s %s%s' %\n                                  (display_path(dest), self.repo_name,\n                                   rev_display))\n                    self.update(dest, rev_options)\n                else:\n                    logger.warn('%s %s in %s exists with URL %s' %\n                                (self.name, self.repo_name,\n                                 display_path(dest), existing_url))\n                    prompt = ('(s)witch, (i)gnore, (w)ipe, (b)ackup ',\n                              ('s', 'i', 'w', 'b'))\n            else:\n                logger.warn('Directory %s already exists, '\n                            'and is not a %s %s.' %\n                            (dest, self.name, self.repo_name))\n                prompt = ('(i)gnore, (w)ipe, (b)ackup ', ('i', 'w', 'b'))\n        if prompt:\n            logger.warn('The plan is to install the %s repository %s' %\n                        (self.name, url))\n            response = ask_path_exists('What to do?  %s' % prompt[0],\n                                       prompt[1])\n\n            if response == 's':\n                logger.notify('Switching %s %s to %s%s' %\n                              (self.repo_name, display_path(dest), url,\n                               rev_display))\n                self.switch(dest, url, rev_options)\n            elif response == 'i':\n                # do nothing\n                pass\n            elif response == 'w':\n                logger.warn('Deleting %s' % display_path(dest))\n                rmtree(dest)\n                checkout = True\n            elif response == 'b':\n                dest_dir = backup_dir(dest)\n                logger.warn('Backing up %s to %s'\n                            % (display_path(dest), dest_dir))\n                shutil.move(dest, dest_dir)\n                checkout = True\n        return checkout\n\n    def unpack(self, location):\n        if os.path.exists(location):\n            rmtree(location)\n        self.obtain(location)\n\n    def get_src_requirement(self, dist, location, find_tags=False):\n        raise NotImplementedError\n\n\ndef get_src_requirement(dist, location, find_tags):\n    version_control = vcs.get_backend_from_location(location)\n    if version_control:\n        return version_control().get_src_requirement(dist, location, find_tags)\n    logger.warn(\n        'cannot determine version of editable source in %s (is not SVN '\n        'checkout, Git clone, Mercurial clone or Bazaar branch)' % location\n    )\n    return dist.as_requirement()\n", "path": "pip/vcs/__init__.py"}], "after_files": [{"content": "\"\"\"Handles all VCS (version control) support\"\"\"\n\nimport os\nimport shutil\n\nfrom pip.compat import urlparse, urllib\nfrom pip.exceptions import BadCommand\nfrom pip.log import logger\nfrom pip.util import (display_path, backup_dir, find_command,\n                      rmtree, ask_path_exists)\n\n\n__all__ = ['vcs', 'get_src_requirement']\n\n\nclass VcsSupport(object):\n    _registry = {}\n    schemes = ['ssh', 'git', 'hg', 'bzr', 'sftp', 'svn']\n\n    def __init__(self):\n        # Register more schemes with urlparse for various version control\n        # systems\n        urlparse.uses_netloc.extend(self.schemes)\n        # Python >= 2.7.4, 3.3 doesn't have uses_fragment\n        if getattr(urlparse, 'uses_fragment', None):\n            urlparse.uses_fragment.extend(self.schemes)\n        super(VcsSupport, self).__init__()\n\n    def __iter__(self):\n        return self._registry.__iter__()\n\n    @property\n    def backends(self):\n        return list(self._registry.values())\n\n    @property\n    def dirnames(self):\n        return [backend.dirname for backend in self.backends]\n\n    @property\n    def all_schemes(self):\n        schemes = []\n        for backend in self.backends:\n            schemes.extend(backend.schemes)\n        return schemes\n\n    def register(self, cls):\n        if not hasattr(cls, 'name'):\n            logger.warn('Cannot register VCS %s' % cls.__name__)\n            return\n        if cls.name not in self._registry:\n            self._registry[cls.name] = cls\n\n    def unregister(self, cls=None, name=None):\n        if name in self._registry:\n            del self._registry[name]\n        elif cls in self._registry.values():\n            del self._registry[cls.name]\n        else:\n            logger.warn('Cannot unregister because no class or name given')\n\n    def get_backend_name(self, location):\n        \"\"\"\n        Return the name of the version control backend if found at given\n        location, e.g. vcs.get_backend_name('/path/to/vcs/checkout')\n        \"\"\"\n        for vc_type in self._registry.values():\n            path = os.path.join(location, vc_type.dirname)\n            if os.path.exists(path):\n                return vc_type.name\n        return None\n\n    def get_backend(self, name):\n        name = name.lower()\n        if name in self._registry:\n            return self._registry[name]\n\n    def get_backend_from_location(self, location):\n        vc_type = self.get_backend_name(location)\n        if vc_type:\n            return self.get_backend(vc_type)\n        return None\n\n\nvcs = VcsSupport()\n\n\nclass VersionControl(object):\n    name = ''\n    dirname = ''\n\n    def __init__(self, url=None, *args, **kwargs):\n        self.url = url\n        self._cmd = None\n        super(VersionControl, self).__init__(*args, **kwargs)\n\n    def _filter(self, line):\n        return (logger.INFO, line)\n\n    def _is_local_repository(self, repo):\n        \"\"\"\n           posix absolute paths start with os.path.sep,\n           win32 ones ones start with drive (like c:\\\\folder)\n        \"\"\"\n        drive, tail = os.path.splitdrive(repo)\n        return repo.startswith(os.path.sep) or drive\n\n    @property\n    def cmd(self):\n        if self._cmd is not None:\n            return self._cmd\n        command = find_command(self.name)\n        logger.info('Found command %r at %r' % (self.name, command))\n        self._cmd = command\n        return command\n\n    def get_url_rev(self):\n        \"\"\"\n        Returns the correct repository URL and revision by parsing the given\n        repository URL\n        \"\"\"\n        error_message = (\n            \"Sorry, '%s' is a malformed VCS url. \"\n            \"The format is <vcs>+<protocol>://<url>, \"\n            \"e.g. svn+http://myrepo/svn/MyApp#egg=MyApp\"\n        )\n        assert '+' in self.url, error_message % self.url\n        url = self.url.split('+', 1)[1]\n        scheme, netloc, path, query, frag = urlparse.urlsplit(url)\n        rev = None\n        if '@' in path:\n            path, rev = path.rsplit('@', 1)\n        url = urlparse.urlunsplit((scheme, netloc, path, query, ''))\n        return url, rev\n\n    def get_info(self, location):\n        \"\"\"\n        Returns (url, revision), where both are strings\n        \"\"\"\n        assert not location.rstrip('/').endswith(self.dirname), \\\n            'Bad directory: %s' % location\n        return self.get_url(location), self.get_revision(location)\n\n    def normalize_url(self, url):\n        \"\"\"\n        Normalize a URL for comparison by unquoting it and removing any\n        trailing slash.\n        \"\"\"\n        return urllib.unquote(url).rstrip('/')\n\n    def compare_urls(self, url1, url2):\n        \"\"\"\n        Compare two repo URLs for identity, ignoring incidental differences.\n        \"\"\"\n        return (self.normalize_url(url1) == self.normalize_url(url2))\n\n    def obtain(self, dest):\n        \"\"\"\n        Called when installing or updating an editable package, takes the\n        source path of the checkout.\n        \"\"\"\n        raise NotImplementedError\n\n    def switch(self, dest, url, rev_options):\n        \"\"\"\n        Switch the repo at ``dest`` to point to ``URL``.\n        \"\"\"\n        raise NotImplemented\n\n    def update(self, dest, rev_options):\n        \"\"\"\n        Update an already-existing repo to the given ``rev_options``.\n        \"\"\"\n        raise NotImplementedError\n\n    def check_destination(self, dest, url, rev_options, rev_display):\n        \"\"\"\n        Prepare a location to receive a checkout/clone.\n\n        Return True if the location is ready for (and requires) a\n        checkout/clone, False otherwise.\n        \"\"\"\n        checkout = True\n        prompt = False\n        if os.path.exists(dest):\n            checkout = False\n            if os.path.exists(os.path.join(dest, self.dirname)):\n                existing_url = self.get_url(dest)\n                if self.compare_urls(existing_url, url):\n                    logger.info('%s in %s exists, and has correct URL (%s)' %\n                                (self.repo_name.title(), display_path(dest),\n                                 url))\n                    logger.notify('Updating %s %s%s' %\n                                  (display_path(dest), self.repo_name,\n                                   rev_display))\n                    self.update(dest, rev_options)\n                else:\n                    logger.warn('%s %s in %s exists with URL %s' %\n                                (self.name, self.repo_name,\n                                 display_path(dest), existing_url))\n                    prompt = ('(s)witch, (i)gnore, (w)ipe, (b)ackup ',\n                              ('s', 'i', 'w', 'b'))\n            else:\n                logger.warn('Directory %s already exists, '\n                            'and is not a %s %s.' %\n                            (dest, self.name, self.repo_name))\n                prompt = ('(i)gnore, (w)ipe, (b)ackup ', ('i', 'w', 'b'))\n        if prompt:\n            logger.warn('The plan is to install the %s repository %s' %\n                        (self.name, url))\n            response = ask_path_exists('What to do?  %s' % prompt[0],\n                                       prompt[1])\n\n            if response == 's':\n                logger.notify('Switching %s %s to %s%s' %\n                              (self.repo_name, display_path(dest), url,\n                               rev_display))\n                self.switch(dest, url, rev_options)\n            elif response == 'i':\n                # do nothing\n                pass\n            elif response == 'w':\n                logger.warn('Deleting %s' % display_path(dest))\n                rmtree(dest)\n                checkout = True\n            elif response == 'b':\n                dest_dir = backup_dir(dest)\n                logger.warn('Backing up %s to %s'\n                            % (display_path(dest), dest_dir))\n                shutil.move(dest, dest_dir)\n                checkout = True\n        return checkout\n\n    def unpack(self, location):\n        if os.path.exists(location):\n            rmtree(location)\n        self.obtain(location)\n\n    def get_src_requirement(self, dist, location, find_tags=False):\n        raise NotImplementedError\n\n\ndef get_src_requirement(dist, location, find_tags):\n    version_control = vcs.get_backend_from_location(location)\n    if version_control:\n        try:\n            return version_control().get_src_requirement(dist,\n                                                         location,\n                                                         find_tags)\n        except BadCommand:\n            logger.warn('cannot determine version of editable source in %s '\n                        '(%s command not found in path)' % (\n                            location, version_control.name))\n            return dist.as_requirement()\n    logger.warn(\n        'cannot determine version of editable source in %s (is not SVN '\n        'checkout, Git clone, Mercurial clone or Bazaar branch)' % location\n    )\n    return dist.as_requirement()\n", "path": "pip/vcs/__init__.py"}]}