We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Bad error message on malformed VCS string
The item in my requirements.txt:

```
git://github.com/alex/django-fixture-generator.git#egg=fixture_generator
```

The resulting error message:

``` python
Downloading/unpacking fixture-generator from git://github.com/alex/django-fixture-generator.git (from -r requirements/development.txt (line 3))
Exception:
Traceback (most recent call last):
  File "/home/alex/.virtualenvs/tracebin/local/lib/python2.7/site-packages/pip-1.0.2-py2.7.egg/pip/basecommand.py", line 126, in main
    self.run(options, args)
  File "/home/alex/.virtualenvs/tracebin/local/lib/python2.7/site-packages/pip-1.0.2-py2.7.egg/pip/commands/install.py", line 223, in run
    requirement_set.prepare_files(finder, force_root_egg_info=self.bundle, bundle=self.bundle)
  File "/home/alex/.virtualenvs/tracebin/local/lib/python2.7/site-packages/pip-1.0.2-py2.7.egg/pip/req.py", line 961, in prepare_files
    self.unpack_url(url, location, self.is_download)
  File "/home/alex/.virtualenvs/tracebin/local/lib/python2.7/site-packages/pip-1.0.2-py2.7.egg/pip/req.py", line 1073, in unpack_url
    return unpack_vcs_link(link, location, only_download)
  File "/home/alex/.virtualenvs/tracebin/local/lib/python2.7/site-packages/pip-1.0.2-py2.7.egg/pip/download.py", line 293, in unpack_vcs_link
    vcs_backend.unpack(location)
  File "/home/alex/.virtualenvs/tracebin/local/lib/python2.7/site-packages/pip-1.0.2-py2.7.egg/pip/vcs/__init__.py", line 225, in unpack
    self.obtain(location)
  File "/home/alex/.virtualenvs/tracebin/local/lib/python2.7/site-packages/pip-1.0.2-py2.7.egg/pip/vcs/git.py", line 97, in obtain
    url, rev = self.get_url_rev()
  File "/home/alex/.virtualenvs/tracebin/local/lib/python2.7/site-packages/pip-1.0.2-py2.7.egg/pip/vcs/git.py", line 183, in get_url_rev
    url, rev = super(Git, self).get_url_rev()
  File "/home/alex/.virtualenvs/tracebin/local/lib/python2.7/site-packages/pip-1.0.2-py2.7.egg/pip/vcs/__init__.py", line 117, in get_url_rev
    url = self.url.split('+', 1)[1]
IndexError: list index out of range
```


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

{"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@@ -115,6 +115,9 @@\n         Returns the correct repository URL and revision by parsing the given\n         repository URL\n         \"\"\"\n+        error_message= \"Sorry, '{}' is a malformed url. In requirements files, the \\\n+format is <vcs>+<protocol>://<url>, e.g. svn+http://myrepo/svn/MyApp#egg=MyApp\"\n+        assert '+' in self.url, error_message.format(self.url)\n         url = self.url.split('+', 1)[1]\n         scheme, netloc, path, query, frag = urlparse.urlsplit(url)\n         rev = None\n", "issue": "Bad error message on malformed VCS string\nThe item in my requirements.txt:\n\n```\ngit://github.com/alex/django-fixture-generator.git#egg=fixture_generator\n```\n\nThe resulting error message:\n\n``` python\nDownloading/unpacking fixture-generator from git://github.com/alex/django-fixture-generator.git (from -r requirements/development.txt (line 3))\nException:\nTraceback (most recent call last):\n  File \"/home/alex/.virtualenvs/tracebin/local/lib/python2.7/site-packages/pip-1.0.2-py2.7.egg/pip/basecommand.py\", line 126, in main\n    self.run(options, args)\n  File \"/home/alex/.virtualenvs/tracebin/local/lib/python2.7/site-packages/pip-1.0.2-py2.7.egg/pip/commands/install.py\", line 223, in run\n    requirement_set.prepare_files(finder, force_root_egg_info=self.bundle, bundle=self.bundle)\n  File \"/home/alex/.virtualenvs/tracebin/local/lib/python2.7/site-packages/pip-1.0.2-py2.7.egg/pip/req.py\", line 961, in prepare_files\n    self.unpack_url(url, location, self.is_download)\n  File \"/home/alex/.virtualenvs/tracebin/local/lib/python2.7/site-packages/pip-1.0.2-py2.7.egg/pip/req.py\", line 1073, in unpack_url\n    return unpack_vcs_link(link, location, only_download)\n  File \"/home/alex/.virtualenvs/tracebin/local/lib/python2.7/site-packages/pip-1.0.2-py2.7.egg/pip/download.py\", line 293, in unpack_vcs_link\n    vcs_backend.unpack(location)\n  File \"/home/alex/.virtualenvs/tracebin/local/lib/python2.7/site-packages/pip-1.0.2-py2.7.egg/pip/vcs/__init__.py\", line 225, in unpack\n    self.obtain(location)\n  File \"/home/alex/.virtualenvs/tracebin/local/lib/python2.7/site-packages/pip-1.0.2-py2.7.egg/pip/vcs/git.py\", line 97, in obtain\n    url, rev = self.get_url_rev()\n  File \"/home/alex/.virtualenvs/tracebin/local/lib/python2.7/site-packages/pip-1.0.2-py2.7.egg/pip/vcs/git.py\", line 183, in get_url_rev\n    url, rev = super(Git, self).get_url_rev()\n  File \"/home/alex/.virtualenvs/tracebin/local/lib/python2.7/site-packages/pip-1.0.2-py2.7.egg/pip/vcs/__init__.py\", line 117, in get_url_rev\n    url = self.url.split('+', 1)[1]\nIndexError: list index out of range\n```\n\n", "before_files": [{"content": "\"\"\"Handles all VCS (version control) support\"\"\"\n\nimport os\nimport shutil\n\nfrom pip.backwardcompat import urlparse, urllib\nfrom pip.log import logger\nfrom pip.util import (display_path, backup_dir, find_command,\n                      ask, 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 systems\n        urlparse.uses_netloc.extend(self.schemes)\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        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), '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 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 parse_vcs_bundle_file(self, content):\n        \"\"\"\n        Takes the contents of the bundled text file that explains how to revert\n        the stripped off version control data of the given package and returns\n        the URL and revision of it.\n        \"\"\"\n        raise NotImplementedError\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('cannot determine version of editable source in %s (is not SVN checkout, Git clone, Mercurial clone or Bazaar branch)' % location)\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.backwardcompat import urlparse, urllib\nfrom pip.log import logger\nfrom pip.util import (display_path, backup_dir, find_command,\n                      ask, 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 systems\n        urlparse.uses_netloc.extend(self.schemes)\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= \"Sorry, '{}' is a malformed url. In requirements files, the \\\nformat is <vcs>+<protocol>://<url>, e.g. svn+http://myrepo/svn/MyApp#egg=MyApp\"\n        assert '+' in self.url, error_message.format(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), '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 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 parse_vcs_bundle_file(self, content):\n        \"\"\"\n        Takes the contents of the bundled text file that explains how to revert\n        the stripped off version control data of the given package and returns\n        the URL and revision of it.\n        \"\"\"\n        raise NotImplementedError\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('cannot determine version of editable source in %s (is not SVN checkout, Git clone, Mercurial clone or Bazaar branch)' % location)\n    return dist.as_requirement()\n", "path": "pip/vcs/__init__.py"}]}