~jk0/nova/xs-ipv6

« back to all changes in this revision

Viewing changes to test/lib/python2.6/site-packages/pip-0.8.1-py2.6.egg/pip/vcs/__init__.py

  • Committer: Tarmac
  • Author(s): Anne Gentle
  • Date: 2011-02-26 17:50:42 UTC
  • mfrom: (747.1.1 delpeskytest)
  • Revision ID: tarmac-20110226175042-htwnmds3fydg3ny1
Did a pull from trunk to be sure I had the latest, then deleted the test directory. I guess it appeared when I started using venv. Doh.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
"""Handles all VCS (version control) support"""
2
 
 
3
 
import os
4
 
import shutil
5
 
import urlparse
6
 
import urllib
7
 
 
8
 
from pip.exceptions import BadCommand
9
 
from pip.log import logger
10
 
from pip.util import display_path, backup_dir, find_command, ask
11
 
 
12
 
 
13
 
__all__ = ['vcs', 'get_src_requirement', 'import_vcs_support']
14
 
 
15
 
 
16
 
class VcsSupport(object):
17
 
    _registry = {}
18
 
    schemes = ['ssh', 'git', 'hg', 'bzr', 'sftp']
19
 
 
20
 
    def __init__(self):
21
 
        # Register more schemes with urlparse for various version control systems
22
 
        urlparse.uses_netloc.extend(self.schemes)
23
 
        urlparse.uses_fragment.extend(self.schemes)
24
 
        super(VcsSupport, self).__init__()
25
 
 
26
 
    def __iter__(self):
27
 
        return self._registry.__iter__()
28
 
 
29
 
    @property
30
 
    def backends(self):
31
 
        return self._registry.values()
32
 
 
33
 
    @property
34
 
    def dirnames(self):
35
 
        return [backend.dirname for backend in self.backends]
36
 
 
37
 
    @property
38
 
    def all_schemes(self):
39
 
        schemes = []
40
 
        for backend in self.backends:
41
 
            schemes.extend(backend.schemes)
42
 
        return schemes
43
 
 
44
 
    def register(self, cls):
45
 
        if not hasattr(cls, 'name'):
46
 
            logger.warn('Cannot register VCS %s' % cls.__name__)
47
 
            return
48
 
        if cls.name not in self._registry:
49
 
            self._registry[cls.name] = cls
50
 
 
51
 
    def unregister(self, cls=None, name=None):
52
 
        if name in self._registry:
53
 
            del self._registry[name]
54
 
        elif cls in self._registry.values():
55
 
            del self._registry[cls.name]
56
 
        else:
57
 
            logger.warn('Cannot unregister because no class or name given')
58
 
 
59
 
    def get_backend_name(self, location):
60
 
        """
61
 
        Return the name of the version control backend if found at given
62
 
        location, e.g. vcs.get_backend_name('/path/to/vcs/checkout')
63
 
        """
64
 
        for vc_type in self._registry.values():
65
 
            path = os.path.join(location, vc_type.dirname)
66
 
            if os.path.exists(path):
67
 
                return vc_type.name
68
 
        return None
69
 
 
70
 
    def get_backend(self, name):
71
 
        name = name.lower()
72
 
        if name in self._registry:
73
 
            return self._registry[name]
74
 
 
75
 
    def get_backend_from_location(self, location):
76
 
        vc_type = self.get_backend_name(location)
77
 
        if vc_type:
78
 
            return self.get_backend(vc_type)
79
 
        return None
80
 
 
81
 
 
82
 
vcs = VcsSupport()
83
 
 
84
 
 
85
 
class VersionControl(object):
86
 
    name = ''
87
 
    dirname = ''
88
 
 
89
 
    def __init__(self, url=None, *args, **kwargs):
90
 
        self.url = url
91
 
        self._cmd = None
92
 
        super(VersionControl, self).__init__(*args, **kwargs)
93
 
 
94
 
    def _filter(self, line):
95
 
        return (logger.INFO, line)
96
 
 
97
 
    def _is_local_repository(self, repo):
98
 
        """
99
 
           posix absolute paths start with os.path.sep,
100
 
           win32 ones ones start with drive (like c:\\folder)
101
 
        """
102
 
        drive, tail = os.path.splitdrive(repo)
103
 
        return repo.startswith(os.path.sep) or drive
104
 
 
105
 
    @property
106
 
    def cmd(self):
107
 
        if self._cmd is not None:
108
 
            return self._cmd
109
 
        command = find_command(self.name)
110
 
        if command is None:
111
 
            raise BadCommand('Cannot find command %r' % 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
 
        url = self.url.split('+', 1)[1]
122
 
        scheme, netloc, path, query, frag = urlparse.urlsplit(url)
123
 
        rev = None
124
 
        if '@' in path:
125
 
            path, rev = path.rsplit('@', 1)
126
 
        url = urlparse.urlunsplit((scheme, netloc, path, query, ''))
127
 
        return url, rev
128
 
 
129
 
    def get_info(self, location):
130
 
        """
131
 
        Returns (url, revision), where both are strings
132
 
        """
133
 
        assert not location.rstrip('/').endswith(self.dirname), 'Bad directory: %s' % location
134
 
        return self.get_url(location), self.get_revision(location)
135
 
 
136
 
    def normalize_url(self, url):
137
 
        """
138
 
        Normalize a URL for comparison by unquoting it and removing any trailing slash.
139
 
        """
140
 
        return urllib.unquote(url).rstrip('/')
141
 
 
142
 
    def compare_urls(self, url1, url2):
143
 
        """
144
 
        Compare two repo URLs for identity, ignoring incidental differences.
145
 
        """
146
 
        return (self.normalize_url(url1) == self.normalize_url(url2))
147
 
 
148
 
    def parse_vcs_bundle_file(self, content):
149
 
        """
150
 
        Takes the contents of the bundled text file that explains how to revert
151
 
        the stripped off version control data of the given package and returns
152
 
        the URL and revision of it.
153
 
        """
154
 
        raise NotImplementedError
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), url))
191
 
                    logger.notify('Updating %s %s%s'
192
 
                                  % (display_path(dest), self.repo_name, rev_display))
193
 
                    self.update(dest, rev_options)
194
 
                else:
195
 
                    logger.warn('%s %s in %s exists with URL %s'
196
 
                                % (self.name, self.repo_name, display_path(dest), existing_url))
197
 
                    prompt = ('(s)witch, (i)gnore, (w)ipe, (b)ackup ', ('s', 'i', 'w', 'b'))
198
 
            else:
199
 
                logger.warn('Directory %s already exists, and is not a %s %s.'
200
 
                            % (dest, self.name, self.repo_name))
201
 
                prompt = ('(i)gnore, (w)ipe, (b)ackup ', ('i', 'w', 'b'))
202
 
        if prompt:
203
 
            logger.warn('The plan is to install the %s repository %s'
204
 
                        % (self.name, url))
205
 
            response = ask('What to do?  %s' % prompt[0], prompt[1])
206
 
 
207
 
            if response == 's':
208
 
                logger.notify('Switching %s %s to %s%s'
209
 
                              % (self.repo_name, display_path(dest), url, rev_display))
210
 
                self.switch(dest, url, rev_options)
211
 
            elif response == 'i':
212
 
                # do nothing
213
 
                pass
214
 
            elif response == 'w':
215
 
                logger.warn('Deleting %s' % display_path(dest))
216
 
                shutil.rmtree(dest)
217
 
                checkout = True
218
 
            elif response == 'b':
219
 
                dest_dir = backup_dir(dest)
220
 
                logger.warn('Backing up %s to %s'
221
 
                            % (display_path(dest), dest_dir))
222
 
                shutil.move(dest, dest_dir)
223
 
                checkout = True
224
 
        return checkout
225
 
 
226
 
    def unpack(self, location):
227
 
        raise NotImplementedError
228
 
 
229
 
    def get_src_requirement(self, dist, location, find_tags=False):
230
 
        raise NotImplementedError
231
 
 
232
 
 
233
 
def get_src_requirement(dist, location, find_tags):
234
 
    version_control = vcs.get_backend_from_location(location)
235
 
    if version_control:
236
 
        return version_control().get_src_requirement(dist, location, find_tags)
237
 
    logger.warn('cannot determine version of editable source in %s (is not SVN checkout, Git clone, Mercurial clone or Bazaar branch)' % location)
238
 
    return dist.as_requirement()