Skip to content

Commit

Permalink
Merge pull request #10893 from peter1000/adds_function_relpath
Browse files Browse the repository at this point in the history
adds_function_relpath, docs, tests
  • Loading branch information
kmsquire committed Apr 21, 2015
2 parents a49ae53 + 13302e6 commit aefa0f9
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 0 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,9 @@ Library improvements
* New `withenv(var=>val, ...) do ... end` function to temporarily
modify environment variables ([#10914]).

* New function `relpath` returns a relative filepath to path either from the current
directory or from an optional start directory ([#10893]).

Deprecated or removed
---------------------

Expand Down Expand Up @@ -1375,4 +1378,5 @@ Too numerous to mention.
[#10844]: https://github.com/JuliaLang/julia/issues/10844
[#10870]: https://github.com/JuliaLang/julia/issues/10870
[#10885]: https://github.com/JuliaLang/julia/issues/10885
[#10893]: https://github.com/JuliaLang/julia/pull/10893
[#10914]: https://github.com/JuliaLang/julia/issues/10914
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,7 @@ export
joinpath,
normpath,
realpath,
relpath,
splitdir,
splitdrive,
splitext,
Expand Down
29 changes: 29 additions & 0 deletions base/path.jl
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,32 @@ end
if c == '/' return homedir()*path[i:end] end
throw(ArgumentError("~user tilde expansion not yet implemented"))
end

function relpath(path::AbstractString, startpath::AbstractString = ".")
isempty(path) && throw(ArgumentError("`path` must be specified"))
isempty(startpath) && throw(ArgumentError("`startpath` must be specified"))
curdir = "."
pardir = ".."
path == startpath && return curdir
path_arr = split(abspath(path), path_separator_re)
start_arr = split(abspath(startpath), path_separator_re)
i = 0
while i < min(length(path_arr), length(start_arr))
i += 1
if path_arr[i] != start_arr[i]
i -= 1
break
end
end
pathpart = join(path_arr[i+1:findlast(x -> !isempty(x), path_arr)], path_separator)
prefix_num = findlast(x -> !isempty(x), start_arr) - i - 1
if prefix_num >= 0
prefix = pardir * path_separator
relpath_ = isempty(pathpart) ?
(prefix^prefix_num) * pardir :
(prefix^prefix_num) * pardir * path_separator * pathpart
else
relpath_ = pathpart
end
return isempty(relpath_) ? curdir : relpath_
end
9 changes: 9 additions & 0 deletions doc/helpdb.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5354,6 +5354,15 @@ Millisecond(v)
"),

("Base","relpath","relpath(path::AbstractString, startpath::AbstractString = ".") -> AbstractString
Return a relative filepath to path either from the current directory or from an optional
start directory.
This is a path computation: the filesystem is not accessed to confirm the existence or
nature of path or startpath.
"),

("Base","expanduser","expanduser(path::AbstractString) -> AbstractString
On Unix systems, replace a tilde character at the start of a path
Expand Down
7 changes: 7 additions & 0 deletions doc/stdlib/file.rst
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,13 @@

Canonicalize a path by expanding symbolic links and removing "." and ".." entries.

.. function:: relpath(path::AbstractString, startpath::AbstractString = ".") -> AbstractString

Return a relative filepath to path either from the current directory or from an optional
start directory.
This is a path computation: the filesystem is not accessed to confirm the existence or
nature of path or startpath.

.. function:: expanduser(path::AbstractString) -> AbstractString

On Unix systems, replace a tilde character at the start of a path with the
Expand Down
82 changes: 82 additions & 0 deletions test/path.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,85 @@
@unix_only @test isabspath("/") == true
@test isabspath("~") == false
@unix_only @test isabspath(expanduser("~")) == true

############################################
# This section tests relpath computation. #
###########################################
function test_relpath()
sep = Base.path_separator
filepaths = [
"$(sep)home$(sep)user$(sep).julia$(sep)Test1$(sep)docs$(sep)api$(sep)Test1.md",
"$(sep)home$(sep)user$(sep).julia$(sep)Test1$(sep)docs$(sep)api$(sep)lib$(sep)file1.md",
"$(sep)home$(sep)user$(sep).julia$(sep)测试2$(sep)docs$(sep)api$(sep)测试2.md",
"$(sep)home$(sep)user$(sep)dir_withendsep$(sep)",
"$(sep)home$(sep)dir2_withendsep$(sep)",
"$(sep)home$(sep)test.md",
"$(sep)home",
# Special cases
"$(sep)",
"$(sep)home$(sep)$(sep)$(sep)"
]
startpaths = [
"$(sep)home$(sep)user$(sep).julia$(sep)Test1$(sep)docs$(sep)api$(sep)genindex.md",
"$(sep)multi_docs$(sep)genindex.md",
"$(sep)home$(sep)user$(sep)dir_withendsep$(sep)",
"$(sep)home$(sep)dir2_withendsep$(sep)",
"$(sep)home$(sep)test.md",
"$(sep)home",
# Special cases
"$(sep)",
"$(sep)home$(sep)$(sep)$(sep)"
]
relpath_expected_results = [
"..$(sep)Test1.md",
"..$(sep)..$(sep)home$(sep)user$(sep).julia$(sep)Test1$(sep)docs$(sep)api$(sep)Test1.md",
"..$(sep).julia$(sep)Test1$(sep)docs$(sep)api$(sep)Test1.md",
"..$(sep)user$(sep).julia$(sep)Test1$(sep)docs$(sep)api$(sep)Test1.md",
"..$(sep)user$(sep).julia$(sep)Test1$(sep)docs$(sep)api$(sep)Test1.md",
"user$(sep).julia$(sep)Test1$(sep)docs$(sep)api$(sep)Test1.md",
"home$(sep)user$(sep).julia$(sep)Test1$(sep)docs$(sep)api$(sep)Test1.md",
"user$(sep).julia$(sep)Test1$(sep)docs$(sep)api$(sep)Test1.md",
"..$(sep)lib$(sep)file1.md",
"..$(sep)..$(sep)home$(sep)user$(sep).julia$(sep)Test1$(sep)docs$(sep)api$(sep)lib$(sep)file1.md",
"..$(sep).julia$(sep)Test1$(sep)docs$(sep)api$(sep)lib$(sep)file1.md",
"..$(sep)user$(sep).julia$(sep)Test1$(sep)docs$(sep)api$(sep)lib$(sep)file1.md",
"..$(sep)user$(sep).julia$(sep)Test1$(sep)docs$(sep)api$(sep)lib$(sep)file1.md",
"user$(sep).julia$(sep)Test1$(sep)docs$(sep)api$(sep)lib$(sep)file1.md",
"home$(sep)user$(sep).julia$(sep)Test1$(sep)docs$(sep)api$(sep)lib$(sep)file1.md",
"user$(sep).julia$(sep)Test1$(sep)docs$(sep)api$(sep)lib$(sep)file1.md",
"..$(sep)..$(sep)..$(sep)..$(sep)测试2$(sep)docs$(sep)api$(sep)测试2.md",
"..$(sep)..$(sep)home$(sep)user$(sep).julia$(sep)测试2$(sep)docs$(sep)api$(sep)测试2.md",
"..$(sep).julia$(sep)测试2$(sep)docs$(sep)api$(sep)测试2.md",
"..$(sep)user$(sep).julia$(sep)测试2$(sep)docs$(sep)api$(sep)测试2.md",
"..$(sep)user$(sep).julia$(sep)测试2$(sep)docs$(sep)api$(sep)测试2.md",
"user$(sep).julia$(sep)测试2$(sep)docs$(sep)api$(sep)测试2.md",
"home$(sep)user$(sep).julia$(sep)测试2$(sep)docs$(sep)api$(sep)测试2.md",
"user$(sep).julia$(sep)测试2$(sep)docs$(sep)api$(sep)测试2.md",
"..$(sep)..$(sep)..$(sep)..$(sep)..$(sep)dir_withendsep",
"..$(sep)..$(sep)home$(sep)user$(sep)dir_withendsep",".","..$(sep)user$(sep)dir_withendsep",
"..$(sep)user$(sep)dir_withendsep","user$(sep)dir_withendsep",
"home$(sep)user$(sep)dir_withendsep","user$(sep)dir_withendsep",
"..$(sep)..$(sep)..$(sep)..$(sep)..$(sep)..$(sep)dir2_withendsep",
"..$(sep)..$(sep)home$(sep)dir2_withendsep","..$(sep)..$(sep)dir2_withendsep",".",
"..$(sep)dir2_withendsep","dir2_withendsep","home$(sep)dir2_withendsep","dir2_withendsep",
"..$(sep)..$(sep)..$(sep)..$(sep)..$(sep)..$(sep)test.md","..$(sep)..$(sep)home$(sep)test.md",
"..$(sep)..$(sep)test.md","..$(sep)test.md",".","test.md","home$(sep)test.md","test.md",
"..$(sep)..$(sep)..$(sep)..$(sep)..$(sep)..","..$(sep)..$(sep)home","..$(sep)..",
"..","..",".","home",".","..$(sep)..$(sep)..$(sep)..$(sep)..$(sep)..$(sep)..","..$(sep)..",
"..$(sep)..$(sep)..","..$(sep)..","..$(sep)..","..",".","..",
"..$(sep)..$(sep)..$(sep)..$(sep)..$(sep)..","..$(sep)..$(sep)home","..$(sep)..",
"..","..",".","home","."
]
idx = 0
for filep in filepaths
for startp in startpaths
res = relpath(filep, startp)
idx += 1
@test res == relpath_expected_results[idx]
end
end
# Additional cases
@test_throws ArgumentError relpath("$(sep)home$(sep)user$(sep)dir_withendsep$(sep)", "")
@test_throws ArgumentError relpath("", "$(sep)home$(sep)user$(sep)dir_withendsep$(sep)")
end
test_relpath()

0 comments on commit aefa0f9

Please sign in to comment.