1
# Bazaar-NG -- distributed version control
1
# Bazaar -- distributed version control
3
# Copyright (C) 2006 by Canonical Ltd
3
# Copyright (C) 2006 Canonical Ltd
5
5
# This program is free software; you can redistribute it and/or modify
6
6
# it under the terms of the GNU General Public License as published by
19
19
"""A collection of function for handling URL operations."""
22
from posixpath import split as _posix_split, normpath as _posix_normpath
25
from bzrlib.lazy_import import lazy_import
26
lazy_import(globals(), """
27
from posixpath import split as _posix_split, normpath as _posix_normpath
27
import bzrlib.errors as errors
31
37
def basename(url, exclude_trailing_slash=True):
76
82
base = local_path_from_url(base)
77
83
path = local_path_from_url(path)
78
return escape(bzrlib.osutils.relpath(base, path))
84
return escape(osutils.relpath(base, path))
81
87
def _find_scheme_and_separator(url):
131
137
scheme = m.group('scheme')
138
# this skips .. normalisation, making http://host/../../..
132
140
path = m.group('path').split('/')
134
142
for chunk in arg.split('/'):
166
174
# importing directly from posixpath allows us to test this
167
175
# on non-posix platforms
168
176
return 'file://' + escape(_posix_normpath(
169
bzrlib.osutils._posix_abspath(path)))
177
osutils._posix_abspath(path)))
172
180
def _win32_local_path_from_url(url):
173
181
"""Convert a url like file:///C:/path/to/foo into C:/path/to/foo"""
174
if not url.startswith('file:///'):
175
raise errors.InvalidURL(url, 'local urls must start with file:///')
182
if not url.startswith('file://'):
183
raise errors.InvalidURL(url, 'local urls must start with file:///, '
184
'UNC path urls must start with file://')
176
185
# We strip off all 3 slashes
177
win32_url = url[len('file:///'):]
178
if (win32_url[0] not in ('abcdefghijklmnopqrstuvwxyz'
186
win32_url = url[len('file:'):]
187
# check for UNC path: //HOST/path
188
if not win32_url.startswith('///'):
189
if (win32_url[2] == '/'
190
or win32_url[3] in '|:'):
191
raise errors.InvalidURL(url, 'Win32 UNC path urls'
192
' have form file://HOST/path')
193
return unescape(win32_url)
194
# usual local path with drive letter
195
if (win32_url[3] not in ('abcdefghijklmnopqrstuvwxyz'
179
196
'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
180
or win32_url[1] not in '|:'
181
or win32_url[2] != '/'):
197
or win32_url[4] not in '|:'
198
or win32_url[5] != '/'):
182
199
raise errors.InvalidURL(url, 'Win32 file urls start with'
183
200
' file:///x:/, where x is a valid drive letter')
184
return win32_url[0].upper() + u':' + unescape(win32_url[2:])
201
return win32_url[3].upper() + u':' + unescape(win32_url[5:])
187
204
def _win32_local_path_to_url(path):
195
212
# which actually strips trailing space characters.
196
213
# The worst part is that under linux ntpath.abspath has different
197
214
# semantics, since 'nt' is not an available module.
198
win32_path = bzrlib.osutils._nt_normpath(
199
bzrlib.osutils._win32_abspath(path)).replace('\\', '/')
215
win32_path = osutils._nt_normpath(
216
osutils._win32_abspath(path)).replace('\\', '/')
217
# check for UNC path \\HOST\path
218
if win32_path.startswith('//'):
219
return 'file:' + escape(win32_path)
200
220
return 'file:///' + win32_path[0].upper() + ':' + escape(win32_path[2:])
251
271
if path[i] not in _url_safe_characters:
252
272
chars = path[i].encode('utf-8')
253
273
path[i] = ''.join(['%%%02X' % ord(c) for c in path[i].encode('utf-8')])
254
return scheme + '://' + ''.join(path)
274
return str(scheme + '://' + ''.join(path))
257
277
def relative_url(base, other):
438
458
_hex_display_map.update((hex,'%'+hex) for hex in _no_decode_hex)
440
460
# These characters should not be escaped
441
_url_safe_characters = set('abcdefghijklmnopqrstuvwxyz'
442
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
461
_url_safe_characters = set(
462
"abcdefghijklmnopqrstuvwxyz" # Lowercase alpha
463
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" # Uppercase alpha
464
"0123456789" # Numbers
465
"_.-!~*'()" # Unreserved characters
466
"/;?:@&=+$," # Reserved characters
467
"%#" # Extra reserved characters
447
470
def unescape_for_display(url, encoding):
448
471
"""Decode what you can for a URL, so that we get a nice looking path.