Skip to content

Commit

Permalink
Remove assumption of ascii paths
Browse files Browse the repository at this point in the history
On for example a linux system with a Japanese locale, the user-dirs.dirs
file can contain paths with japanese characters, breaking the
byte-offset-based path processing. To fix this, we switch to
chop/chopprefix instead, and while we're at it make a similar fix in the
setxdg macro implementation.

A test based on the Japanese user-dirs.dirs is created.

Reported-by: ujimushi at Slashdot Japan <10514830+ujimushi@users.noreply.github.com>
  • Loading branch information
tecosaur committed Feb 17, 2024
1 parent ea3ad56 commit 19d9b46
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 13 deletions.
21 changes: 21 additions & 0 deletions src/BaseDirs.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
module BaseDirs

# Compat
@static if VERSION < v"1.8"
function chopsuffix(s::Union{String, SubString{String}},
suffix::Union{String, SubString{String}})
if !isempty(suffix) && endswith(s, suffix)
astart = ncodeunits(s) - ncodeunits(suffix) + 1
@inbounds SubString(s, firstindex(s), prevind(s, astart))
else
SubString(s)
end
end
function chopprefix(s::Union{String, SubString{String}},
prefix::Union{String, SubString{String}})
if startswith(s, prefix)
SubString(s, 1 + ncodeunits(prefix))
else
SubString(s)
end
end
end

include("variables.jl")

function reload end
Expand Down
14 changes: 3 additions & 11 deletions src/internals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,14 @@ export @defaccessor, @setxdg, @setxdgs
@static if Sys.isunix()
macro setxdg(envvar::Symbol, default)
quote $(esc(envvar))[] = if haskey(ENV, $("XDG_$envvar")) && !isempty(ENV[$("XDG_$envvar")])
path = ENV[$("XDG_$envvar")]
if endswith(path, first(Base.Filesystem.path_separator))
path[begin:end-1]
else path end
chopsuffix(ENV[$("XDG_$envvar")], Base.Filesystem.path_separator)
else expanduser($(esc(default))) end
end
end
else
macro setxdg(envvar::Symbol, default)
quote $(esc(envvar))[] = if haskey(ENV, $("XDG_$envvar")) && !isempty(ENV[$("XDG_$envvar")])
path = ENV[$("XDG_$envvar")]
if endswith(path, first(Base.Filesystem.path_separator))
path[begin:end-1]
else path end
chopsuffix(ENV[$("XDG_$envvar")], Base.Filesystem.path_separator)
else $(esc(default)) end
end
end
Expand All @@ -32,9 +26,7 @@ end
macro setxdgs(envvar::Symbol, defaults)
quote $(esc(envvar))[] = if haskey(ENV, $("XDG_$envvar")) && !isempty(ENV[$("XDG_$envvar")])
map(split(ENV[$("XDG_$envvar")], ':')) do path
if endswith(path, first(Base.Filesystem.path_separator))
path[begin:end-1]
else path end
chopsuffix(path, Base.Filesystem.path_separator)
end
else $(esc(defaults)) end
end
Expand Down
4 changes: 2 additions & 2 deletions src/unix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ function parseuserdirs(configdir::String)
key, value = split(line, '=', limit=2)
if key in validnames
if startswith(value, '"') && endswith(value, '"')
value = unescape_string(value[2:end-1])
value = unescape_string(chop(value, head=1, tail=1))
end
if startswith(value, "\$HOME")
value = string(homedir(), value[6:end])
value = string(homedir(), chopprefix(value, "\$HOME"))
end
if startswith(value, '/')
push!(keys, Symbol(key))
Expand Down
28 changes: 28 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,34 @@ elseif Sys.isunix()
@test BaseDirs.User.fonts() == ["$usr/.local/share/fonts", "$usr/.fonts"]
@test BaseDirs.User.applications() == ["$usr/.local/share/applications"]
end
@testset "User (customised)" begin
userdirs_jpn = raw"""
XDG_DESKTOP_DIR="$HOME/デスクトップ"
XDG_DOWNLOAD_DIR="$HOME/ダウンロード"
XDG_TEMPLATES_DIR="$HOME/テンプレート"
XDG_PUBLICSHARE_DIR="$HOME/公開"
XDG_DOCUMENTS_DIR="$HOME/ドキュメント"
XDG_MUSIC_DIR="$HOME/ミュージック"
XDG_PICTURES_DIR="$HOME/ピクチャ"
XDG_VIDEOS_DIR="$HOME/ビデオ"
"""
userdirs_file = joinpath(BaseDirs.CONFIG_HOME[], "user-dirs.dirs")
isfile(userdirs_file) &&
mv(userdirs_file, userdirs_file * ".backup")
write(userdirs_file, userdirs_jpn)
@test BaseDirs.reload() === nothing
@test BaseDirs.User.desktop() == "$usr/デスクトップ"
@test BaseDirs.User.downloads() == "$usr/ダウンロード"
@test BaseDirs.User.documents() == "$usr/ドキュメント"
@test BaseDirs.User.music() == "$usr/ミュージック"
@test BaseDirs.User.pictures() == "$usr/ピクチャ"
@test BaseDirs.User.videos() == "$usr/ビデオ"
@test BaseDirs.User.templates() == "$usr/テンプレート"
@test BaseDirs.User.public() == "$usr/公開"
rm(userdirs_file)
isfile(userdirs_file * ".backup") &&
mv(userdirs_file * ".backup", userdirs_file)
end
@testset "System" begin
@test BaseDirs.System.data() == ["/usr/local/share", "/usr/share"]
@test BaseDirs.System.config() == ["/etc/xdg"]
Expand Down

0 comments on commit 19d9b46

Please sign in to comment.