Skip to content

Commit 245bc09

Browse files
committed
Fix behavior of Path.expand/2. Improve docstrings
1 parent 0abeef0 commit 245bc09

File tree

2 files changed

+50
-31
lines changed

2 files changed

+50
-31
lines changed

lib/elixir/lib/path.ex

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
defmodule Path do
22
@moduledoc """
33
This module provides conveniences for manipulating or
4-
retrieving filesystem paths.
4+
retrieving file system paths.
55
6-
The functions on this module may receive a char list or
7-
a binary as argument and will return the given type.
6+
The functions in this module may receive a char list or
7+
a binary as argument and will return a value of the same
8+
type.
89
910
The majority of the functions in this module do not
10-
interact with the file system, unless some few functions
11-
that needs to query the filesystem to retrieve paths
12-
(like `Path.wildcard` and `Path.expand`).
11+
interact with the file system, except for a few functions
12+
that require it (like `Path.wildcard` and `Path.expand`).
1313
"""
1414

1515
alias :filename, as: FN
@@ -18,9 +18,8 @@ defmodule Path do
1818
@type r :: char_list | binary
1919

2020
@doc """
21-
Converts the given filename and returns an absolute name.
22-
Differently from `Path.expand/1`, no attempt is made to
23-
resolve `..`, `.` or `~`.
21+
Converts the given path to an absolute one. Differently from
22+
`Path.expand/1`, no attempt is made to resolve `..`, `.` or `~`.
2423
2524
## Unix examples
2625
@@ -43,9 +42,8 @@ defmodule Path do
4342
end
4443

4544
@doc """
46-
Converts the given filename and returns an absolute name
47-
relative to the given location. If the path is already
48-
an absolute path, the relative path is ignored.
45+
Builds a path from `relative_to` to `path`. If `path` is already
46+
an absolute path, `relative_to` is ignored. See also `Path.relative/2`.
4947
5048
Differently from `Path.expand/2`, no attempt is made to
5149
resolve `..`, `.` or `~`.
@@ -64,8 +62,8 @@ defmodule Path do
6462
end
6563

6664
@doc """
67-
Expands the path by returning its absolute name and expanding
68-
any `.` and `..` characters.
65+
Converts the path to an absolute one and expands
66+
any `.` and `..` characters and a leading `~`.
6967
7068
## Examples
7169
@@ -78,20 +76,29 @@ defmodule Path do
7876
end
7977

8078
@doc """
81-
Expands the path to the relative location and expanding
82-
any `.` and `..` characters. If the path is already an
83-
absolute path, the relative location is ignored.
79+
Expands the path relative to the path given as the second argument
80+
expanding any `.` and `..` characters. If the path is already an
81+
absolute path, `relative_to` is ignored.
82+
83+
Note, that this function treats `path` with leading `~` as
84+
an absolute one.
85+
86+
The second argument is first expanded to an absolute path.
8487
8588
## Examples
8689
90+
# Assuming that the absolute path to baz is /quux/baz
91+
Path.expand("foo/bar/../bar", "baz")
92+
#=> "/quux/baz/foo/bar"
93+
8794
iex> Path.expand("foo/bar/../bar", "/baz")
8895
"/baz/foo/bar"
8996
iex> Path.expand("/foo/bar/../bar", "/baz")
9097
"/foo/bar"
9198
9299
"""
93100
def expand(path, relative_to) do
94-
normalize FN.absname(FN.absname(expand_home(path), relative_to), get_cwd(path))
101+
normalize FN.absname(FN.absname(expand_home(path), expand_home(relative_to)), get_cwd(path))
95102
end
96103

97104
@doc """
@@ -102,6 +109,7 @@ defmodule Path do
102109
Path.type("/usr/local/bin") #=> :absolute
103110
Path.type("usr/local/bin") #=> :relative
104111
Path.type("../usr/local/bin") #=> :relative
112+
Path.type("~/file") #=> :relative
105113
106114
## Windows examples
107115
@@ -185,8 +193,9 @@ defmodule Path do
185193

186194
@doc """
187195
Returns the given `path` relative to the given `from` path.
196+
In other words, it tries to strip the `from` prefix from `path`.
188197
189-
This function does not query the filesystem, so it assumes
198+
This function does not query the file system, so it assumes
190199
no symlinks in between the paths.
191200
192201
In case a direct relative path cannot be found, it returns
@@ -267,20 +276,22 @@ defmodule Path do
267276
end
268277

269278
@doc """
270-
Return the `directory` component of `path`.
279+
Returns the directory component of `path`.
271280
272281
## Examples
273282
274283
Path.dirname("/foo/bar.ex")
275-
#=> "foo"
284+
#=> "/foo"
285+
Path.dirname("/foo/bar/baz.ex")
286+
#=> "/foo/bar"
276287
277288
"""
278289
def dirname(path) do
279290
FN.dirname(path)
280291
end
281292

282293
@doc """
283-
Return the `extension` of the last component of `path`.
294+
Returns the extension of the last component of `path`.
284295
285296
## Examples
286297
@@ -326,8 +337,8 @@ defmodule Path do
326337
end
327338

328339
@doc """
329-
Returns a string with one or more paths components joint by the path separator.
330-
This function should be used to convert a list of strings in a path.
340+
Returns a string with one or more path components joined by the path separator.
341+
This function should be used to convert a list of strings to a path.
331342
332343
## Examples
333344
@@ -409,8 +420,8 @@ defmodule Path do
409420
:lists.reverse(name)
410421

411422
@doc """
412-
Returns a list with the path splitted by the path separator.
413-
If an empty string is given, then it returns the root path.
423+
Returns a list with the path split by the path separator.
424+
If an empty string is given, returns the root path.
414425
415426
## Examples
416427
@@ -450,7 +461,7 @@ defmodule Path do
450461
451462
Imagine you have a directory called `projects` with three Elixir projects
452463
inside of it: `elixir`, `ex_doc` and `dynamo`. You can find all `.beam` files
453-
inside their ebin directories all projects as follows:
464+
inside the ebin directory of each project as follows:
454465
455466
Path.wildcard("projects/*/ebin/**/*.beam")
456467
@@ -520,4 +531,4 @@ defmodule Path do
520531
defp normalize([], acc) do
521532
join Enum.reverse(acc)
522533
end
523-
end
534+
end

lib/elixir/test/elixir/path_test.exs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,18 @@ defmodule PathTest do
9898
end
9999

100100
test :expand_path_with_user_home do
101-
assert System.user_home! == Path.expand("~")
101+
home = System.user_home!
102+
103+
assert home == Path.expand("~")
102104
assert is_binary Path.expand("~/foo")
103105

104-
assert (System.user_home! |> :unicode.characters_to_list) == Path.expand('~')
106+
assert (home |> :unicode.characters_to_list) == Path.expand('~')
105107
assert is_list Path.expand('~/foo')
108+
109+
assert Path.expand("~/file") == Path.join(home, "file")
110+
assert Path.expand("~/file", "whatever") == Path.join(home, "file")
111+
assert Path.expand("file", Path.expand("~")) == Path.expand("~/file")
112+
assert Path.expand("file", "~") == Path.join(home, "file")
106113
end
107114

108115
test :expand_path_with_binary do
@@ -171,6 +178,7 @@ defmodule PathTest do
171178

172179
test :dirname_with_binary do
173180
assert Path.dirname("/foo/bar.ex") == "/foo"
181+
assert Path.dirname("foo/bar.ex") == "foo"
174182
assert Path.dirname("~/foo/bar.ex") == "~/foo"
175183
assert Path.dirname("/foo/bar/baz/") == "/foo/bar/baz"
176184
end
@@ -240,4 +248,4 @@ defmodule PathTest do
240248
assert Path.split('foo') == ['foo']
241249
assert Path.split('/foo/bar') == ['/', 'foo', 'bar']
242250
end
243-
end
251+
end

0 commit comments

Comments
 (0)