Skip to content

Commit

Permalink
make tempname on windows match unix behavior. fixes #9053 (#25530)
Browse files Browse the repository at this point in the history
also deprecate `tempname(::UInt32)` and add a warning to the docs.
  • Loading branch information
JeffBezanson authored Jan 15, 2018
1 parent e88cbd9 commit 5e2ff12
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 21 deletions.
5 changes: 4 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,9 @@ This section lists changes that do not have deprecation warnings.
to get the old behavior (only "space" characters are considered as
word separators), use the keyword `wordsep=isspace`.

* The `tempname` function used to create a file on Windows but not on other
platforms. It now never creates a file ([#9053]).

Library improvements
--------------------

Expand Down Expand Up @@ -1194,4 +1197,4 @@ Command-line option changes
[#25231]: https://github.com/JuliaLang/julia/issues/25231
[#25365]: https://github.com/JuliaLang/julia/issues/25365
[#25424]: https://github.com/JuliaLang/julia/issues/25424
[#25532]: https://github.com/JuliaLang/julia/issues/25532
[#25532]: https://github.com/JuliaLang/julia/issues/25532
7 changes: 7 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2789,6 +2789,13 @@ end
@deprecate findn(x::AbstractMatrix) (I = find(!iszero, x); (getindex.(I, 1), getindex.(I, 2)))
@deprecate findn(a::AbstractArray{T, N}) where {T, N} (I = find(!iszero, x); ntuple(i -> getindex.(I, i), N))

# issue #9053
if Sys.iswindows()
function Filesystem.tempname(uunique::UInt32)
error("`tempname(::UInt32)` is discontinued.")
end
end

# END 0.7 deprecations

# BEGIN 1.0 deprecations
Expand Down
32 changes: 27 additions & 5 deletions base/file.jl
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,9 @@ function tempdir()
resize!(temppath,lentemppath)
return transcode(String, temppath)
end
tempname(uunique::UInt32=UInt32(0)) = tempname(tempdir(), uunique)

const temp_prefix = cwstring("jl_")
function tempname(temppath::AbstractString,uunique::UInt32)
function _win_tempname(temppath::AbstractString, uunique::UInt32)
tempp = cwstring(temppath)
tname = Vector{UInt16}(uninitialized, 32767)
uunique = ccall(:GetTempFileNameW,stdcall,UInt32,(Ptr{UInt16},Ptr{UInt16},UInt32,Ptr{UInt16}), tempp,temp_prefix,uunique,tname)
Expand All @@ -280,7 +280,7 @@ function tempname(temppath::AbstractString,uunique::UInt32)
end

function mktemp(parent=tempdir())
filename = tempname(parent, UInt32(0))
filename = _win_tempname(parent, UInt32(0))
return (filename, Base.open(filename, "r+"))
end

Expand All @@ -290,7 +290,7 @@ function mktempdir(parent=tempdir())
if (seed & typemax(UInt16)) == 0
seed += 1
end
filename = tempname(parent, seed)
filename = _win_tempname(parent, seed)
ret = ccall(:_wmkdir, Int32, (Ptr{UInt16},), cwstring(filename))
if ret == 0
return filename
Expand All @@ -300,6 +300,21 @@ function mktempdir(parent=tempdir())
end
end

function tempname()
parent = tempdir()
seed::UInt32 = rand(UInt32)
while true
if (seed & typemax(UInt16)) == 0
seed += 1
end
filename = _win_tempname(parent, seed)
if !ispath(filename)
return filename
end
seed += 1
end
end

else # !windows
# Obtain a temporary filename.
function tempname()
Expand Down Expand Up @@ -343,7 +358,14 @@ tempdir()
"""
tempname()
Generate a unique temporary file path.
Generate a temporary file path. This function only returns a path; no file is
created. The path is likely to be unique, but this cannot be guaranteed.
!!! warning
This can lead to race conditions if another process obtains the same
file name and creates the file before you are able to.
Using [`mktemp()`](@ref) is recommended instead.
"""
tempname()

Expand Down
16 changes: 5 additions & 11 deletions base/pkg/entry.jl
Original file line number Diff line number Diff line change
Expand Up @@ -633,19 +633,13 @@ function build!(pkgs::Vector, seen::Set, errfile::AbstractString)
end

function build!(pkgs::Vector, errs::Dict, seen::Set=Set())
errfile = tempname()
touch(errfile) # create empty file
try
mktemp() do errfile, f
build!(pkgs, seen, errfile)
open(errfile, "r") do f
while !eof(f)
pkg = deserialize(f)
err = deserialize(f)
errs[pkg] = err
end
while !eof(f)
pkg = deserialize(f)
err = deserialize(f)
errs[pkg] = err
end
finally
isfile(errfile) && Base.rm(errfile)
end
end

Expand Down
8 changes: 4 additions & 4 deletions test/file.jl
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,10 @@ close(s)
my_tempdir = tempdir()
@test isdir(my_tempdir) == true

path = tempname()
# Issue #9053.
@test ispath(path) == Sys.iswindows()
ispath(path) && rm(path)
let path = tempname()
# issue #9053
@test !ispath(path)
end

(p, f) = mktemp()
print(f, "Here is some text")
Expand Down
1 change: 1 addition & 0 deletions test/replcompletions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ end

if Sys.iswindows()
tmp = tempname()
touch(tmp)
path = dirname(tmp)
file = basename(tmp)
temp_name = basename(path)
Expand Down

1 comment on commit 5e2ff12

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Executing the daily benchmark build, I will reply here when finished:

@nanosoldier runbenchmarks(ALL, isdaily = true)

Please sign in to comment.