~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/urlutils.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-03-28 02:28:09 UTC
  • mfrom: (2379.1.1 hpss-urlutils)
  • Revision ID: pqm@pqm.ubuntu.com-20070328022809-40aa40f8edf4e502
(robertc) urlutils improvements split out from the hpss branch (Andrew Bennetts, Robert Collins)

Show diffs side-by-side

added added

removed removed

Lines of Context:
117
117
        join('http://foo', 'bar') => 'http://foo/bar'
118
118
        join('http://foo', 'bar', '../baz') => 'http://foo/baz'
119
119
    """
120
 
    m = _url_scheme_re.match(base)
 
120
    if not args:
 
121
        return base
 
122
    match = _url_scheme_re.match(base)
121
123
    scheme = None
122
 
    if m:
123
 
        scheme = m.group('scheme')
124
 
        path = m.group('path').split('/')
 
124
    if match:
 
125
        scheme = match.group('scheme')
 
126
        path = match.group('path').split('/')
125
127
        if path[-1:] == ['']:
126
128
            # Strip off a trailing slash
127
129
            # This helps both when we are at the root, and when
130
132
    else:
131
133
        path = base.split('/')
132
134
 
 
135
    if scheme is not None and len(path) >= 1:
 
136
        host = path[:1]
 
137
        # the path should be represented as an abs path.
 
138
        # we know this must be absolute because of the presence of a URL scheme.
 
139
        remove_root = True
 
140
        path = [''] + path[1:]
 
141
    else:
 
142
        # create an empty host, but dont alter the path - this might be a
 
143
        # relative url fragment.
 
144
        host = []
 
145
        remove_root = False
 
146
 
133
147
    for arg in args:
134
 
        m = _url_scheme_re.match(arg)
135
 
        if m:
 
148
        match = _url_scheme_re.match(arg)
 
149
        if match:
136
150
            # Absolute URL
137
 
            scheme = m.group('scheme')
 
151
            scheme = match.group('scheme')
138
152
            # this skips .. normalisation, making http://host/../../..
139
153
            # be rather strange.
140
 
            path = m.group('path').split('/')
 
154
            path = match.group('path').split('/')
 
155
            # set the host and path according to new absolute URL, discarding
 
156
            # any previous values.
 
157
            # XXX: duplicates mess from earlier in this function.  This URL
 
158
            # manipulation code needs some cleaning up.
 
159
            if scheme is not None and len(path) >= 1:
 
160
                host = path[:1]
 
161
                path = path[1:]
 
162
                # url scheme implies absolute path.
 
163
                path = [''] + path
 
164
            else:
 
165
                # no url scheme we take the path as is.
 
166
                host = []
141
167
        else:
142
 
            for chunk in arg.split('/'):
143
 
                if chunk == '.':
144
 
                    continue
145
 
                elif chunk == '..':
146
 
                    if len(path) >= 2:
147
 
                        # Don't pop off the host portion
148
 
                        path.pop()
149
 
                    else:
150
 
                        raise errors.InvalidURLJoin('Cannot go above root',
151
 
                                base, args)
152
 
                else:
153
 
                    path.append(chunk)
 
168
            path = '/'.join(path)
 
169
            path = joinpath(path, arg)
 
170
            path = path.split('/')
 
171
    if remove_root and path[0:1] == ['']:
 
172
        del path[0]
 
173
    if host:
 
174
        # Remove the leading slash from the path, so long as it isn't also the
 
175
        # trailing slash, which we want to keep if present.
 
176
        if path and path[0] == '' and len(path) > 1:
 
177
            del path[0]
 
178
        path = host + path
154
179
 
155
180
    if scheme is None:
156
181
        return '/'.join(path)
157
182
    return scheme + '://' + '/'.join(path)
158
183
 
159
184
 
 
185
def joinpath(base, *args):
 
186
    """Join URL path segments to a URL path segment.
 
187
    
 
188
    This is somewhat like osutils.joinpath, but intended for URLs.
 
189
 
 
190
    XXX: this duplicates some normalisation logic, and also duplicates a lot of
 
191
    path handling logic that already exists in some Transport implementations.
 
192
    We really should try to have exactly one place in the code base responsible
 
193
    for combining paths of URLs.
 
194
    """
 
195
    path = base.split('/')
 
196
    if len(path) > 1 and path[-1] == '':
 
197
        #If the path ends in a trailing /, remove it.
 
198
        path.pop()
 
199
    for arg in args:
 
200
        if arg.startswith('/'):
 
201
            path = []
 
202
        for chunk in arg.split('/'):
 
203
            if chunk == '.':
 
204
                continue
 
205
            elif chunk == '..':
 
206
                if path == ['']:
 
207
                    raise errors.InvalidURLJoin('Cannot go above root',
 
208
                            base, args)
 
209
                path.pop()
 
210
            else:
 
211
                path.append(chunk)
 
212
    if path == ['']:
 
213
        return '/'
 
214
    else:
 
215
        return '/'.join(path)
 
216
 
 
217
 
160
218
# jam 20060502 Sorted to 'l' because the final target is 'local_path_from_url'
161
219
def _posix_local_path_from_url(url):
162
220
    """Convert a url like file:///path/to/foo into /path/to/foo"""