forked from JuliaLang/julia
-
Notifications
You must be signed in to change notification settings - Fork 0
/
download.jl
104 lines (93 loc) · 3.82 KB
/
download.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# This file is a part of Julia. License is MIT: https://julialang.org/license
# file downloading
if Sys.iswindows()
function download_powershell(url::AbstractString, filename::AbstractString)
ps = joinpath(get(ENV, "SYSTEMROOT", "C:\\Windows"), "System32\\WindowsPowerShell\\v1.0\\powershell.exe")
tls12 = "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12"
client = "New-Object System.Net.Webclient"
# in the following we escape ' with '' (see https://ss64.com/ps/syntax-esc.html)
downloadfile = "($client).DownloadFile('$(replace(url, "'" => "''"))', '$(replace(filename, "'" => "''"))')"
# PowerShell v3 or later is required for Tls12
proc = run(pipeline(`$ps -Version 3 -NoProfile -Command "$tls12; $downloadfile"`; stderr=stderr); wait=false)
if !success(proc)
if proc.exitcode % Int32 == -393216
# appears to be "wrong version" exit code, based on
# https://docs.microsoft.com/en-us/azure/cloud-services/cloud-services-startup-tasks-common
@error "Downloading files requires Windows Management Framework 3.0 or later."
end
pipeline_error(proc)
end
return filename
end
end
function find_curl()
if Sys.isapple() && Sys.isexecutable("/usr/bin/curl")
"/usr/bin/curl"
elseif Sys.iswindows() && Sys.isexecutable(joinpath(get(ENV, "SYSTEMROOT", "C:\\Windows"), "System32\\curl.exe"))
joinpath(get(ENV, "SYSTEMROOT", "C:\\Windows"), "System32\\curl.exe")
elseif !Sys.iswindows() && Sys.which("curl") !== nothing
"curl"
else
nothing
end
end
function download_curl(curl_exe::AbstractString, url::AbstractString, filename::AbstractString)
err = PipeBuffer()
process = run(pipeline(`$curl_exe -s -S -g -L -f -o $filename $url`, stderr=err), wait=false)
if !success(process)
error_msg = readline(err)
@error "Download failed: $error_msg"
pipeline_error(process)
end
return filename
end
const DOWNLOAD_HOOKS = Callable[]
function download_url(url::AbstractString)
for hook in DOWNLOAD_HOOKS
url = String(hook(url)::AbstractString)
end
return url
end
function download(url::AbstractString, filename::AbstractString)
url = download_url(url)
curl_exe = find_curl()
if curl_exe !== nothing
return download_curl(curl_exe, url, filename)
elseif Sys.iswindows()
return download_powershell(url, filename)
elseif Sys.which("wget") !== nothing
try
run(`wget -O $filename $url`)
catch
rm(filename, force=true) # wget always creates a file
rethrow()
end
elseif Sys.which("busybox") !== nothing
try
run(`busybox wget -O $filename $url`)
catch
rm(filename, force=true) # wget always creates a file
rethrow()
end
elseif Sys.which("fetch") !== nothing
run(`fetch -f $filename $url`)
else
error("No download agent available; install curl, wget, busybox or fetch.")
end
return filename
end
function download(url::AbstractString)
filename = tempname()
download(url, filename)
end
"""
download(url::AbstractString, [localfile::AbstractString])
Download a file from the given url, optionally renaming it to the given local file name. If
no filename is given this will download into a randomly-named file in your temp directory.
Note that this function relies on the availability of external tools such as `curl`, `wget`
or `fetch` to download the file and is provided for convenience. For production use or
situations in which more options are needed, please use a package that provides the desired
functionality instead.
Returns the filename of the downloaded file.
"""
download(url, filename)