diff options
| author | V1K1NGbg <victor@ilchev.com> | 2024-08-23 21:34:04 +0300 |
|---|---|---|
| committer | V1K1NGbg <victor@ilchev.com> | 2024-08-23 21:34:04 +0300 |
| commit | 650d7ad17188b4ec0e54a283311f62d90ec69537 (patch) | |
| tree | ba7e8d2534a37e38a01414156823bc5851f35c9f | |
| parent | fd9ee23b415ae406f0133679b5214d38fff225ad (diff) | |
| download | luarocks-650d7ad17188b4ec0e54a283311f62d90ec69537.tar.gz luarocks-650d7ad17188b4ec0e54a283311f62d90ec69537.tar.bz2 luarocks-650d7ad17188b4ec0e54a283311f62d90ec69537.zip | |
fetch
| -rw-r--r-- | src/luarocks/fetch.tl | 246 |
1 files changed, 127 insertions, 119 deletions
diff --git a/src/luarocks/fetch.tl b/src/luarocks/fetch.tl index b4927529..222b2194 100644 --- a/src/luarocks/fetch.tl +++ b/src/luarocks/fetch.tl | |||
| @@ -1,6 +1,15 @@ | |||
| 1 | 1 | ||
| 2 | --- Functions related to fetching and loading local and remote files. | 2 | --- Functions related to fetching and loading local and remote files. |
| 3 | local record fetch | 3 | local record fetch |
| 4 | fetch_caching: function(string, ?string): string, string, string, boolean | ||
| 5 | fetch_url: function(string, ?string, ?boolean, ?string): string, string, string, boolean | ||
| 6 | fetch_url_at_temp_dir: function(string, string, ?string, ?boolean): string, string, string | ||
| 7 | find_base_dir: function(string, string, string, ?string): string, string | ||
| 8 | fetch_and_unpack_rock: function(string, ?string, ?boolean): string, string, string | ||
| 9 | load_local_rockspec: function(string, ?boolean): Rockspec, string | ||
| 10 | load_rockspec: function(string, ?string, ?boolean): Rockspec, string, string | ||
| 11 | find_rockspec_source_dir: function(Rockspec, string): boolean, string | ||
| 12 | fetch_sources: function(Rockspec, boolean, ?string): string, string, string, string, string | ||
| 4 | record Fetch | 13 | record Fetch |
| 5 | get_sources: function(Rockspec, boolean, ?string): string, string | 14 | get_sources: function(Rockspec, boolean, ?string): string, string |
| 6 | end | 15 | end |
| @@ -15,10 +24,78 @@ local util = require("luarocks.util") | |||
| 15 | local cfg = require("luarocks.core.cfg") | 24 | local cfg = require("luarocks.core.cfg") |
| 16 | 25 | ||
| 17 | local type Fetch = fetch.Fetch | 26 | local type Fetch = fetch.Fetch |
| 18 | local type Lock = fs.Lock --! | 27 | local type Lock = fs.Lock |
| 19 | local type Rockspec = require("luarocks.core.types.rockspec").Rockspec | 28 | local type Rockspec = require("luarocks.core.types.rockspec").Rockspec |
| 20 | 29 | ||
| 21 | 30 | ||
| 31 | --- Fetch a local or remote file, using a local cache directory. | ||
| 32 | -- Make a remote or local URL/pathname local, fetching the file if necessary. | ||
| 33 | -- Other "fetch" and "load" functions use this function to obtain files. | ||
| 34 | -- If a local pathname is given, it is returned as a result. | ||
| 35 | -- @param url string: a local pathname or a remote URL. | ||
| 36 | -- @param mirroring string: mirroring mode. | ||
| 37 | -- If set to "no_mirror", then rocks_servers mirror configuration is not used. | ||
| 38 | -- @return (string, nil, nil, boolean) or (nil, string, [string]): | ||
| 39 | -- in case of success: | ||
| 40 | -- * the absolute local pathname for the fetched file | ||
| 41 | -- * nil | ||
| 42 | -- * nil | ||
| 43 | -- * `true` if the file was fetched from cache | ||
| 44 | -- in case of failure: | ||
| 45 | -- * nil | ||
| 46 | -- * an error message | ||
| 47 | -- * an optional error code. | ||
| 48 | function fetch.fetch_caching(url: string, mirroring?: string): string, string, string, boolean | ||
| 49 | local repo_url, filename = url:match("^(.*)/([^/]+)$") | ||
| 50 | local name = repo_url:gsub("[/:]","_") | ||
| 51 | local cache_dir = dir.path(cfg.local_cache, name) | ||
| 52 | local ok = fs.make_dir(cache_dir) | ||
| 53 | |||
| 54 | local cachefile = dir.path(cache_dir, filename) | ||
| 55 | local checkfile = cachefile .. ".check" | ||
| 56 | |||
| 57 | if (fs.file_age(checkfile) < 10 or | ||
| 58 | cfg.aggressive_cache and (not name:match("^manifest"))) and fs.exists(cachefile) | ||
| 59 | then | ||
| 60 | return cachefile, nil, nil, true | ||
| 61 | end | ||
| 62 | |||
| 63 | local lock, errlock: Lock, string | ||
| 64 | if ok then | ||
| 65 | lock, errlock = fs.lock_access(cache_dir) | ||
| 66 | end | ||
| 67 | |||
| 68 | if not (ok and lock) then | ||
| 69 | cfg.local_cache = fs.make_temp_dir("local_cache") | ||
| 70 | if not cfg.local_cache then | ||
| 71 | return nil, "Failed creating temporary local_cache directory" | ||
| 72 | end | ||
| 73 | cache_dir = dir.path(cfg.local_cache, name) | ||
| 74 | ok = fs.make_dir(cache_dir) | ||
| 75 | if not ok then | ||
| 76 | return nil, "Failed creating temporary cache directory "..cache_dir | ||
| 77 | end | ||
| 78 | lock = fs.lock_access(cache_dir) | ||
| 79 | end | ||
| 80 | |||
| 81 | local file, err, errcode, from_cache = fetch.fetch_url(url, cachefile, true, mirroring) | ||
| 82 | if not file then | ||
| 83 | fs.unlock_access(lock) | ||
| 84 | return nil, err or "Failed downloading "..url, errcode | ||
| 85 | end | ||
| 86 | |||
| 87 | local fd, erropen = io.open(checkfile, "wb") | ||
| 88 | if erropen then | ||
| 89 | fs.unlock_access(lock) | ||
| 90 | return nil, erropen | ||
| 91 | end | ||
| 92 | fd:write("!") | ||
| 93 | fd:close() | ||
| 94 | |||
| 95 | fs.unlock_access(lock) | ||
| 96 | return file, nil, nil, from_cache | ||
| 97 | end | ||
| 98 | |||
| 22 | local function ensure_trailing_slash(url: string): string | 99 | local function ensure_trailing_slash(url: string): string |
| 23 | return (url:gsub("/*$", "/")) | 100 | return (url:gsub("/*$", "/")) |
| 24 | end | 101 | end |
| @@ -125,76 +202,6 @@ function fetch.fetch_url(url: string, filename?: string, cache?: boolean, mirror | |||
| 125 | end | 202 | end |
| 126 | end | 203 | end |
| 127 | 204 | ||
| 128 | |||
| 129 | --- Fetch a local or remote file, using a local cache directory. | ||
| 130 | -- Make a remote or local URL/pathname local, fetching the file if necessary. | ||
| 131 | -- Other "fetch" and "load" functions use this function to obtain files. | ||
| 132 | -- If a local pathname is given, it is returned as a result. | ||
| 133 | -- @param url string: a local pathname or a remote URL. | ||
| 134 | -- @param mirroring string: mirroring mode. | ||
| 135 | -- If set to "no_mirror", then rocks_servers mirror configuration is not used. | ||
| 136 | -- @return (string, nil, nil, boolean) or (nil, string, [string]): | ||
| 137 | -- in case of success: | ||
| 138 | -- * the absolute local pathname for the fetched file | ||
| 139 | -- * nil | ||
| 140 | -- * nil | ||
| 141 | -- * `true` if the file was fetched from cache | ||
| 142 | -- in case of failure: | ||
| 143 | -- * nil | ||
| 144 | -- * an error message | ||
| 145 | -- * an optional error code. | ||
| 146 | function fetch.fetch_caching(url: string, mirroring?: string): string, string, string, boolean | ||
| 147 | local repo_url, filename = url:match("^(.*)/([^/]+)$") | ||
| 148 | local name = repo_url:gsub("[/:]","_") | ||
| 149 | local cache_dir = dir.path(cfg.local_cache, name) | ||
| 150 | local ok = fs.make_dir(cache_dir) | ||
| 151 | |||
| 152 | local cachefile = dir.path(cache_dir, filename) | ||
| 153 | local checkfile = cachefile .. ".check" | ||
| 154 | |||
| 155 | if (fs.file_age(checkfile) < 10 or | ||
| 156 | cfg.aggressive_cache and (not name:match("^manifest"))) and fs.exists(cachefile) | ||
| 157 | then | ||
| 158 | return cachefile, nil, nil, true | ||
| 159 | end | ||
| 160 | |||
| 161 | local lock, errlock: Lock, string | ||
| 162 | if ok then | ||
| 163 | lock, errlock = fs.lock_access(cache_dir) | ||
| 164 | end | ||
| 165 | |||
| 166 | if not (ok and lock) then | ||
| 167 | cfg.local_cache = fs.make_temp_dir("local_cache") | ||
| 168 | if not cfg.local_cache then | ||
| 169 | return nil, "Failed creating temporary local_cache directory" | ||
| 170 | end | ||
| 171 | cache_dir = dir.path(cfg.local_cache, name) | ||
| 172 | ok = fs.make_dir(cache_dir) | ||
| 173 | if not ok then | ||
| 174 | return nil, "Failed creating temporary cache directory "..cache_dir | ||
| 175 | end | ||
| 176 | lock = fs.lock_access(cache_dir) | ||
| 177 | end | ||
| 178 | |||
| 179 | local file, err, errcode, from_cache = fetch.fetch_url(url, cachefile, true, mirroring) | ||
| 180 | if not file then | ||
| 181 | fs.unlock_access(lock) | ||
| 182 | return nil, err or "Failed downloading "..url, errcode | ||
| 183 | end | ||
| 184 | |||
| 185 | local fd, erropen = io.open(checkfile, "wb") | ||
| 186 | if erropen then | ||
| 187 | fs.unlock_access(lock) | ||
| 188 | return nil, erropen | ||
| 189 | end | ||
| 190 | fd:write("!") | ||
| 191 | fd:close() | ||
| 192 | |||
| 193 | fs.unlock_access(lock) | ||
| 194 | return file, nil, nil, from_cache | ||
| 195 | end | ||
| 196 | |||
| 197 | |||
| 198 | --- For remote URLs, create a temporary directory and download URL inside it. | 205 | --- For remote URLs, create a temporary directory and download URL inside it. |
| 199 | -- This temporary directory will be deleted on program termination. | 206 | -- This temporary directory will be deleted on program termination. |
| 200 | -- For local URLs, just return the local pathname and its directory. | 207 | -- For local URLs, just return the local pathname and its directory. |
| @@ -250,54 +257,6 @@ function fetch.fetch_url_at_temp_dir(url: string, tmpname: string, filename?: st | |||
| 250 | end | 257 | end |
| 251 | end | 258 | end |
| 252 | 259 | ||
| 253 | function fetch.find_rockspec_source_dir(rockspec: Rockspec, store_dir: string): boolean, string | ||
| 254 | local ok, err = fs.change_dir(store_dir) | ||
| 255 | if not ok then return nil, err end | ||
| 256 | |||
| 257 | local file_count, dir_count = 0, 0 | ||
| 258 | local found_dir: string | ||
| 259 | |||
| 260 | if rockspec.source.dir and fs.exists(rockspec.source.dir) then | ||
| 261 | ok, err = true, nil | ||
| 262 | elseif rockspec.source.file and rockspec.source.dir then | ||
| 263 | ok, err = nil, "Directory "..rockspec.source.dir.." not found inside archive "..rockspec.source.file | ||
| 264 | elseif not rockspec.source.dir_set then -- and rockspec:format_is_at_least("3.0") then | ||
| 265 | |||
| 266 | local name = dir.base_name(rockspec.source.file or rockspec.source.url or "") | ||
| 267 | |||
| 268 | if name:match("%.lua$") or name:match("%.c$") then | ||
| 269 | if fs.is_file(name) then | ||
| 270 | rockspec.source.dir = "." | ||
| 271 | ok, err = true, nil | ||
| 272 | end | ||
| 273 | end | ||
| 274 | |||
| 275 | if not rockspec.source.dir then | ||
| 276 | for file in fs.dir() do | ||
| 277 | file_count = file_count + 1 | ||
| 278 | if fs.is_dir(file) then | ||
| 279 | dir_count = dir_count + 1 | ||
| 280 | found_dir = file | ||
| 281 | end | ||
| 282 | end | ||
| 283 | |||
| 284 | if dir_count == 1 then | ||
| 285 | rockspec.source.dir = found_dir | ||
| 286 | ok, err = true, nil | ||
| 287 | else | ||
| 288 | ok, err = nil, "Could not determine source directory from rock contents (" .. tostring(file_count).." file(s), "..tostring(dir_count).." dir(s))" | ||
| 289 | end | ||
| 290 | end | ||
| 291 | else | ||
| 292 | ok, err = nil, "Could not determine source directory, please set source.dir in rockspec." | ||
| 293 | end | ||
| 294 | |||
| 295 | fs.pop_dir() | ||
| 296 | |||
| 297 | assert(rockspec.source.dir or not ok) | ||
| 298 | return ok, err | ||
| 299 | end | ||
| 300 | |||
| 301 | -- Determine base directory of a fetched URL by extracting its | 260 | -- Determine base directory of a fetched URL by extracting its |
| 302 | -- archive and looking for a directory in the root. | 261 | -- archive and looking for a directory in the root. |
| 303 | -- @param file string: absolute local pathname of the fetched file | 262 | -- @param file string: absolute local pathname of the fetched file |
| @@ -351,6 +310,7 @@ function fetch.find_base_dir(file: string, temp_dir: string, src_url: string, sr | |||
| 351 | return inferred_dir, found_dir | 310 | return inferred_dir, found_dir |
| 352 | end | 311 | end |
| 353 | 312 | ||
| 313 | |||
| 354 | local function fetch_and_verify_signature_for(url: string, filename: string, tmpdir: string): string, string, string | 314 | local function fetch_and_verify_signature_for(url: string, filename: string, tmpdir: string): string, string, string |
| 355 | local sig_url = signing.signature_url(url) | 315 | local sig_url = signing.signature_url(url) |
| 356 | local sig_file, errfetch, errcode = fetch.fetch_url_at_temp_dir(sig_url, tmpdir) | 316 | local sig_file, errfetch, errcode = fetch.fetch_url_at_temp_dir(sig_url, tmpdir) |
| @@ -554,6 +514,54 @@ function fetch.get_sources(rockspec: Rockspec, extract: boolean, dest_dir?: stri | |||
| 554 | return source_file, store_dir | 514 | return source_file, store_dir |
| 555 | end | 515 | end |
| 556 | 516 | ||
| 517 | function fetch.find_rockspec_source_dir(rockspec: Rockspec, store_dir: string): boolean, string | ||
| 518 | local ok, err = fs.change_dir(store_dir) | ||
| 519 | if not ok then return nil, err end | ||
| 520 | |||
| 521 | local file_count, dir_count = 0, 0 | ||
| 522 | local found_dir: string | ||
| 523 | |||
| 524 | if rockspec.source.dir and fs.exists(rockspec.source.dir) then | ||
| 525 | ok, err = true, nil | ||
| 526 | elseif rockspec.source.file and rockspec.source.dir then | ||
| 527 | ok, err = nil, "Directory "..rockspec.source.dir.." not found inside archive "..rockspec.source.file | ||
| 528 | elseif not rockspec.source.dir_set then -- and rockspec:format_is_at_least("3.0") then | ||
| 529 | |||
| 530 | local name = dir.base_name(rockspec.source.file or rockspec.source.url or "") | ||
| 531 | |||
| 532 | if name:match("%.lua$") or name:match("%.c$") then | ||
| 533 | if fs.is_file(name) then | ||
| 534 | rockspec.source.dir = "." | ||
| 535 | ok, err = true, nil | ||
| 536 | end | ||
| 537 | end | ||
| 538 | |||
| 539 | if not rockspec.source.dir then | ||
| 540 | for file in fs.dir() do | ||
| 541 | file_count = file_count + 1 | ||
| 542 | if fs.is_dir(file) then | ||
| 543 | dir_count = dir_count + 1 | ||
| 544 | found_dir = file | ||
| 545 | end | ||
| 546 | end | ||
| 547 | |||
| 548 | if dir_count == 1 then | ||
| 549 | rockspec.source.dir = found_dir | ||
| 550 | ok, err = true, nil | ||
| 551 | else | ||
| 552 | ok, err = nil, "Could not determine source directory from rock contents (" .. tostring(file_count).." file(s), "..tostring(dir_count).." dir(s))" | ||
| 553 | end | ||
| 554 | end | ||
| 555 | else | ||
| 556 | ok, err = nil, "Could not determine source directory, please set source.dir in rockspec." | ||
| 557 | end | ||
| 558 | |||
| 559 | fs.pop_dir() | ||
| 560 | |||
| 561 | assert(rockspec.source.dir or not ok) | ||
| 562 | return ok, err | ||
| 563 | end | ||
| 564 | |||
| 557 | --- Download sources for building a rock, calling the appropriate protocol method. | 565 | --- Download sources for building a rock, calling the appropriate protocol method. |
| 558 | -- @param rockspec table: The rockspec table | 566 | -- @param rockspec table: The rockspec table |
| 559 | -- @param extract boolean: When downloading compressed formats, whether to extract | 567 | -- @param extract boolean: When downloading compressed formats, whether to extract |
