1
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):
168
174
# importing directly from posixpath allows us to test this
169
175
# on non-posix platforms
170
176
return 'file://' + escape(_posix_normpath(
171
bzrlib.osutils._posix_abspath(path)))
177
osutils._posix_abspath(path)))
174
180
def _win32_local_path_from_url(url):
175
181
"""Convert a url like file:///C:/path/to/foo into C:/path/to/foo"""
176
if not url.startswith('file:///'):
177
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://')
178
185
# We strip off all 3 slashes
179
win32_url = url[len('file:///'):]
180
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'
181
196
'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
182
or win32_url[1] not in '|:'
183
or win32_url[2] != '/'):
197
or win32_url[4] not in '|:'
198
or win32_url[5] != '/'):
184
199
raise errors.InvalidURL(url, 'Win32 file urls start with'
185
200
' file:///x:/, where x is a valid drive letter')
186
return win32_url[0].upper() + u':' + unescape(win32_url[2:])
201
return win32_url[3].upper() + u':' + unescape(win32_url[5:])
189
204
def _win32_local_path_to_url(path):
197
212
# which actually strips trailing space characters.
198
213
# The worst part is that under linux ntpath.abspath has different
199
214
# semantics, since 'nt' is not an available module.
200
win32_path = bzrlib.osutils._nt_normpath(
201
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)
202
220
return 'file:///' + win32_path[0].upper() + ':' + escape(win32_path[2:])
253
271
if path[i] not in _url_safe_characters:
254
272
chars = path[i].encode('utf-8')
255
273
path[i] = ''.join(['%%%02X' % ord(c) for c in path[i].encode('utf-8')])
256
return scheme + '://' + ''.join(path)
274
return str(scheme + '://' + ''.join(path))
259
277
def relative_url(base, other):
440
458
_hex_display_map.update((hex,'%'+hex) for hex in _no_decode_hex)
442
460
# These characters should not be escaped
443
_url_safe_characters = set('abcdefghijklmnopqrstuvwxyz'
444
'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
449
470
def unescape_for_display(url, encoding):
450
471
"""Decode what you can for a URL, so that we get a nice looking path.