25
27
import bzrlib.osutils
30
def basename(url, exclude_trailing_slash=True):
31
"""Return the last component of a URL.
33
:param url: The URL in question
34
:param exclude_trailing_slash: If the url looks like "path/to/foo/"
35
ignore the final slash and return 'foo' rather than ''
36
:return: Just the final component of the URL. This can return ''
37
if you don't exclude_trailing_slash, or if you are at the
40
return split(url, exclude_trailing_slash=exclude_trailing_slash)[1]
43
def dirname(url, exclude_trailing_slash=True):
44
"""Return the parent directory of the given path.
46
:param url: Relative or absolute URL
47
:param exclude_trailing_slash: Remove a final slash
48
(treat http://host/foo/ as http://host/foo, but
49
http://host/ stays http://host/)
50
:return: Everything in the URL except the last path chunk
52
# TODO: jam 20060502 This was named dirname to be consistent
53
# with the os functions, but maybe "parent" would be better
54
return split(url, exclude_trailing_slash=exclude_trailing_slash)[0]
28
57
def escape(relpath):
29
58
"""Escape relpath to be a valid url."""
30
59
if isinstance(relpath, unicode):
48
77
return escape(bzrlib.osutils.relpath(base, path))
80
def _find_scheme_and_separator(url):
81
"""Find the scheme separator (://) and the first path separator
83
This is just a helper functions for other path utilities.
84
It could probably be replaced by urlparse
86
scheme_loc = url.find('://')
90
# Find the path separating slash
91
# (first slash after the ://)
92
first_path_slash = url.find('/', scheme_loc+3)
93
if first_path_slash == -1:
94
return scheme_loc, None
95
return scheme_loc, first_path_slash
51
98
# jam 20060502 Sorted to 'l' because the final target is 'local_path_from_url'
52
99
def _posix_local_path_from_url(url):
53
100
"""Convert a url like file:///path/to/foo into /path/to/foo"""
107
154
MIN_ABS_FILEURL_LENGTH = len('file:///C|/')
110
def basename(url, exclude_trailing_slash=True):
111
"""Return the last component of a URL.
157
def split(url, exclude_trailing_slash=True):
158
"""Split a URL into its parent directory and a child directory.
113
:param url: The URL in question
114
:param exclude_trailing_slash: If the url looks like "path/to/foo/"
115
ignore the final slash and return 'foo' rather than ''
160
:param url: A relative or absolute URL
161
:param exclude_trailing_slash: Strip off a final '/' if it is part
162
of the path (but not if it is part of the protocol specification)
117
if exclude_trailing_slash:
118
url = strip_trailing_slash(url)
164
scheme_loc, first_path_slash = _find_scheme_and_separator(url)
166
if first_path_slash is None:
167
# We have either a relative path, or no separating slash
168
if scheme_loc is None:
170
if exclude_trailing_slash and url.endswith('/'):
172
return _posix_split(url)
174
# Scheme with no path
177
# We have a fully defined path
178
url_base = url[:first_path_slash] # http://host, file://
179
path = url[first_path_slash:] # /file/foo
181
if sys.platform == 'win32' and url.startswith('file:///'):
182
# Strip off the drive letter
183
if path[2:3] not in '\\/':
184
raise InvalidURL(url,
185
'win32 file:/// paths need a drive letter')
186
url_base += path[1:4] # file:///C|/
189
if exclude_trailing_slash and len(path) > 1 and path.endswith('/'):
191
head, tail = _posix_split(path)
192
return url_base + head, tail
120
195
def strip_trailing_slash(url):
121
196
"""Strip trailing slash, except for root paths.
146
221
# of a win32 path is actually the drive letter
147
222
if len(url) > MIN_ABS_FILEURL_LENGTH:
149
scheme_loc = url.find('://')
224
scheme_loc, first_path_slash = _find_scheme_and_separator(url)
225
if scheme_loc is None:
151
226
# This is a relative path, as it has no scheme
152
227
# so just chop off the last character
155
# Find the path separating slash
156
# (first slash after the ://)
157
first_path_slash = url.find('/', scheme_loc+3)
158
if first_path_slash == -1 or first_path_slash == len(url)-1:
230
if first_path_slash is None or first_path_slash == len(url)-1:
159
231
# Don't chop off anything if the only slash is the path
160
232
# separating slash