Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add prefix argument to mktempdir() #23634

Closed
wants to merge 20 commits into from
Closed

Add prefix argument to mktempdir() #23634

wants to merge 20 commits into from

Conversation

sambitdash
Copy link
Contributor

@sambitdash sambitdash commented Sep 8, 2017

Continuation of #23237, which has all review comments (remerging and rebasing detached the old PR and I cannot reopen it).

Fixes #22922

@sambitdash
Copy link
Contributor Author

@nalimilan, @fredrikekre, @vtjnash, @kshyatt, Please review #23237 here.

@nalimilan Comments on the test cases are incorporated.

On the base/file.jl waiting on the further comments on approach for readdir vs. readlink way of handling the req variable in libuv.

base/file.jl Outdated
template = prefix*"XXXXXX"
tpath = joinpath(parent, template)

req = Libc.malloc(_sizeof_uv_fs)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Decision to be taken if readdir or readlink approach be taken in allocating this variable. @vtjnash to recommend.

base/file.jl Outdated
eventloop(), req, tpath, C_NULL)
if ret < 0
ccall(:uv_fs_req_cleanup, Void, (Ptr{Void},), req)
uv_error("mktempdir", ret)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Formatting to be fixed.

Copy link
Member

@nalimilan nalimilan left a comment

Choose a reason for hiding this comment

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

Thanks, should be good after the few test fixes and validation by @vtjnash.

test/file.jl Outdated
end

else
# '/' is accepted in a prefix but affects the overall path and permissions.
Copy link
Member

Choose a reason for hiding this comment

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

/ does not seem to be accepted, according to the test.

Copy link
Contributor Author

@sambitdash sambitdash Sep 8, 2017

Choose a reason for hiding this comment

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

/ only as the first character of a prefix creates problems. If a path is formed by $parent/someval/ where a path may exist in the system like say /tmp/. It will work. So technically, '/' is supported as a prefix character if the final path is writable by the process.

julia> mktempdir("/";prefix="tmp/")
"/tmp/9dLil5"

julia> 

julia> mktempdir("/";prefix="tmp/s")
"/tmp/sZZDLWl"

julia> mktempdir(;prefix="/")
ERROR: mktempdir: permission denied (EACCES)
Stacktrace:
 [1] uv_error at ./libuv.jl:68 [inlined]
 [2] #mktempdir#12(::String, ::Function, ::String) at ./file.jl:359
 [3] (::getfield(Base.Filesystem, Symbol("#kw##mktempdir")))(::Array{Any,1}, ::typeof(mktempdir), ::String) at ./<missing>:0 (repeats 2 times)

julia> mktempdir(;prefix="ss/")
ERROR: mktempdir: no such file or directory (ENOENT)
Stacktrace:
 [1] uv_error at ./libuv.jl:68 [inlined]
 [2] #mktempdir#12(::String, ::Function, ::String) at ./file.jl:359
 [3] (::getfield(Base.Filesystem, Symbol("#kw##mktempdir")))(::Array{Any,1}, ::typeof(mktempdir), ::String) at ./<missing>:0 (repeats 2 times)

julia> mkdir("/tmp/ss");mktempdir(;prefix="ss/")
"/tmp/ss/ZDAbPm"

julia> 

Copy link
Member

Choose a reason for hiding this comment

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

OK, so just make the comment more explicit.

test/file.jl Outdated
mkdir("c:/mydir")
# The temp directory created is of form "C:\\XXXXXX"
mktempdir("c:/mydir"; prefix="c:/") do tmpdir
filename = basename(tmpdir)
Copy link
Member

Choose a reason for hiding this comment

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

Better also test the path before the base name to ensure that what the comment says actually happens. Same below and on Unix.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you expect me to test for the following?

mktempdir("c:/mydir"; prefix="c:/") do tmpdir
   @test isdir(tmpdir)  
          # Does not makes much of sense as mktempdir() will create the dir() anyway. 
          # Our focus is mostly the name of the dir created. 
          # Those must be tested as part of regular mktempdir (without prefix) test case. 
   filename = basename(tmpdir)

The file already has a large number of mktempdir(without prefix) test cases.

Copy link
Member

Choose a reason for hiding this comment

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

I meant that since you say "The temp directory created is of form "C:\XXXXXX"", you should actually test that it's the case, i.e. that startswith(tempdir, C:\\").

@nalimilan nalimilan changed the title I22922 - Issue being addressed. The state is same as #23237 Add prefix argument to mktempdir() Sep 8, 2017
base/file.jl Outdated
@@ -356,12 +339,33 @@ is an open file object for this path.
mktemp(parent)

"""
mktempdir(parent=tempdir())
mktempdir(parent=tempdir(); prefix="$temp_prefix")
Copy link
Sponsor Member

Choose a reason for hiding this comment

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

"$temp_prefix" == temp_prefix

Copy link
Member

Choose a reason for hiding this comment

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

The idea is to use the value of the global variable rather than repeating it. Seems to work as expected:

julia> x = 1
1

julia> """x = "$x" """
       x
x

help?> x

  x = "1" 

Copy link
Sponsor Member

Choose a reason for hiding this comment

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

My mistake --- I didn't notice this was in a doc string :)

Copy link
Sponsor Member

Choose a reason for hiding this comment

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

Technically $(repr(temp_prefix)) is more correct in case there are weird characters in the prefix (seems unlikely, but it is possible).

test/file.jl Outdated
# The API accepts "c:/ and c:\\" as valid prefixes.
# The parent directory is ignored in that case.

mkdir("c:/mydir")
Copy link
Member

Choose a reason for hiding this comment

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

In most cases the user running Julia won't have access to that path (fortunately), so we'll have to find something else. Maybe pass tempdir() as a prefix, since we know we can write there?

test/file.jl Outdated
filename = basename(tmpdir)
@test length(filename) == 6
end
rm("c:/mydir")
Copy link
Member

Choose a reason for hiding this comment

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

Would be nice to also remove the directory in other cases.

@vtjnash
Copy link
Sponsor Member

vtjnash commented Sep 8, 2017

On the base/file.jl waiting on the further comments on approach for readdir vs. readlink way of handling the req variable in libuv.

Yikes! That's quite a mess of different approaches in there. OTOH, you can use either approach here.

@sambitdash
Copy link
Contributor Author

Considering the comment from @vtjnash, I have committed only the formatting changes needed in the base/file.jl. That should address all the comments so far received on the PR.

Copy link
Member

@nalimilan nalimilan left a comment

Choose a reason for hiding this comment

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

Looks good to me, as long as @vtjnash agrees.

@sambitdash
Copy link
Contributor Author

The errors on CircleCI do not seem relevant to the PR and Travis is stuck for some reason.

@sambitdash
Copy link
Contributor Author

Both the Travis and CircleCI seem to report spurious errors.

@sambitdash
Copy link
Contributor Author

closing and reopening to rerun tests.

@sambitdash sambitdash closed this Sep 22, 2017
@sambitdash sambitdash reopened this Sep 22, 2017
@sambitdash
Copy link
Contributor Author

Errors reported by Travis and CircleCI seem to be unrelated to the check-in. In fact in the earlier iterations the 64-bit version on Travis was passing while the Mac OS X tests didn't even kick off. Please review the changes for merge if any changes are needed let me know.

@nalimilan
Copy link
Member

@vtjnash Merge?

base/file.jl Outdated
if ret < 0
ccall(:uv_fs_req_cleanup, Void, (Ptr{Void},), req)
uv_error("mktempdir", ret)
assert(false)
Copy link
Sponsor Member

Choose a reason for hiding this comment

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

don't need this assert

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed in latest check-in.

base/file.jl Outdated

Create a temporary directory in the `parent` directory and return its path.
If `parent` does not exist, throw an error.
If `parent` does not exist, throw an error. An optional `prefix` to the directory name can
Copy link
Sponsor Member

Choose a reason for hiding this comment

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

The wrapping seems odd here. If you wrap once at the period, I think the rest will fit on the following line.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in latest check-in.

base/file.jl Outdated
mktempdir(parent)
function mktempdir(parent=tempdir(); prefix="$temp_prefix")
template = prefix*"XXXXXX"
tpath = joinpath(parent, template)
Copy link
Sponsor Member

Choose a reason for hiding this comment

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

I think the intention of this API was to compute simply:
tpath = "$(parent)$(path_separator)$(template)XXXXXX"

Copy link
Member

Choose a reason for hiding this comment

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

You mean that it's simpler/more efficient to allocate the string in a single pass?

Copy link
Sponsor Member

Choose a reason for hiding this comment

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

That doesn't matter here. However, the goal of the API appears to be to compute the simpler operation, not joinpath.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

joinpath has 2 functions:

  1. Use the relevant $(path_separator)
  2. Provide a sane path relevant to the OS by stripping end separator.
     ismatch(path_separator_re, a[end:end]) ? string(C,a,b) :
                                             string(C,a,pathsep(a,b),b)

If the input to parent variable ends with a $(path_separator) then the path created will have 2 consecutive $path_separator values. It does not fail but is not the correct return value.

Example:

julia> mktempdir("/tmp/"; prefix="abc")
"/tmp//abclEMi2T"

julia> mktempdir("/"; prefix="tmp/")
"//tmp/rXRggu"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@vtjnash Can you review and suggest if joinpath should be removed from the code.

Copy link
Sponsor Member

Choose a reason for hiding this comment

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

Yes, it should. But to your point, yes we can add some logic here to avoid duplicating the path separator if already present at the end of parent:

if ismatch(path_separator_re, parent[end:end])
    tpath = "$(parent)$(template)XXXXXX"
else
    tpath = "$(parent)$(path_separator)$(template)XXXXXX"
end

@vtjnash
Copy link
Sponsor Member

vtjnash commented Sep 25, 2017

Sorry for all of the incremental review. I know that's really annoying. But should be almost good to go :)

The libuv is used for this implementation in a platform independent
manner.
1. drive letters as prefix
2. Unicode symbols as prefix instead of codes.
Revert "Consolidate pinv tests (#23627)"

This reverts commit 0a8b120.
Revert "Consolidate pinv tests (#23627)"

This reverts commit 0a8b120.
Revert "Revert "Consolidate pinv tests (#23627)""

This reverts commit 1c68698.
@sambitdash
Copy link
Contributor Author

@StefanKarpinski, @vtjnash,

There has been almost a few months we have been working on this PR. And I see very sporadic reviews and review fixes invariably gets into merge conflicts and rebase resolutions that unnecessarily complicate the check-ins. If we do not see much priority in this feature, may be we should discard this feature from the product. I think I have checked-in the last functional code at least 10 days back yet no further update.

@StefanKarpinski
Copy link
Sponsor Member

It's not that we don't want this functionality, but that this needs careful review before merging and people are busy – we're trying to get Julia 1.0 ready very soon. Adding features can always be done in the future. Is there some part of this PR that breaks existing functionality?

@nalimilan
Copy link
Member

AFAICT this should be ready to go, the remaining discussions where mostly about the best coding patterns.

@StefanKarpinski
Copy link
Sponsor Member

StefanKarpinski commented Oct 17, 2017

@nalimilan, could you review it, fix the conflicts and merge if it's good to go? (Please squash.)

@nalimilan
Copy link
Member

I've approved it already, @vtjnash is the one who had comments.

@StefanKarpinski
Copy link
Sponsor Member

@vtjnash, please approve if you feel that your comments have been addressed.

@ViralBShah
Copy link
Member

Any reason still pending?

@nalimilan nalimilan requested a review from vtjnash March 21, 2018 14:00
@ViralBShah ViralBShah added the triage This should be discussed on a triage call label Apr 2, 2018
@@ -381,13 +393,14 @@ function mktemp(fn::Function, parent=tempdir())
end

"""
mktempdir(f::Function, parent=tempdir())
mktempdir(f::Function, parent=tempdir(); prefix="$(repr(temp_prefix))")
Copy link
Sponsor Member

Choose a reason for hiding this comment

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

I think this will include two sets of quotes (quotes are included in the output of repr of a string).

Copy link
Member

Choose a reason for hiding this comment

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

See previous comment: #23634 (comment)

@StefanKarpinski
Copy link
Sponsor Member

This is non-breaking and still not correct. Removing the triage label.

@StefanKarpinski StefanKarpinski removed the triage This should be discussed on a triage call label Apr 5, 2018
@StefanKarpinski StefanKarpinski added this to the 1.x milestone Apr 5, 2018

tpath = "$(parent)$(path_separator)$(prefix)XXXXXX"
Copy link
Sponsor Member

Choose a reason for hiding this comment

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

If prefix contains the letter X this is going to be wrong; it's hard to say if that's avoidable or not, given the way the underlying uv_fs_mkdtemp API works.

Copy link
Sponsor Member

Choose a reason for hiding this comment

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

My understanding is that the last 6 characters need to be X, but it doesn't matter what the other characters are.

Copy link
Member

Choose a reason for hiding this comment

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

Yes. It's not even clear why these chars need to be X rather than any other ASCII char.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Links to documentation for uv_fs_mkdtemp and mkdtemp given below:

http://docs.libuv.org/en/v1.x/fs.html
https://linux.die.net/man/3/mkdtemp

@JeffBezanson
Copy link
Sponsor Member

This is a new feature so doesn't need to be triaged right now.

@tpapp
Copy link
Contributor

tpapp commented Feb 25, 2019

It would be great to revive this PR, as the feature is quite convenient.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

mktempdir() should provide an option of a prefix very similar to you can do with mkdtemp in posix
7 participants