aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorV1K1NGbg <victor@ilchev.com>2024-08-23 21:34:04 +0300
committerV1K1NGbg <victor@ilchev.com>2024-08-23 21:34:04 +0300
commit650d7ad17188b4ec0e54a283311f62d90ec69537 (patch)
treeba7e8d2534a37e38a01414156823bc5851f35c9f
parentfd9ee23b415ae406f0133679b5214d38fff225ad (diff)
downloadluarocks-650d7ad17188b4ec0e54a283311f62d90ec69537.tar.gz
luarocks-650d7ad17188b4ec0e54a283311f62d90ec69537.tar.bz2
luarocks-650d7ad17188b4ec0e54a283311f62d90ec69537.zip
fetch
-rw-r--r--src/luarocks/fetch.tl246
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.
3local record fetch 3local 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")
15local cfg = require("luarocks.core.cfg") 24local cfg = require("luarocks.core.cfg")
16 25
17local type Fetch = fetch.Fetch 26local type Fetch = fetch.Fetch
18local type Lock = fs.Lock --! 27local type Lock = fs.Lock
19local type Rockspec = require("luarocks.core.types.rockspec").Rockspec 28local 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.
48function 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
97end
98
22local function ensure_trailing_slash(url: string): string 99local function ensure_trailing_slash(url: string): string
23 return (url:gsub("/*$", "/")) 100 return (url:gsub("/*$", "/"))
24end 101end
@@ -125,76 +202,6 @@ function fetch.fetch_url(url: string, filename?: string, cache?: boolean, mirror
125 end 202 end
126end 203end
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.
146function 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
195end
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
251end 258end
252 259
253function 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
299end
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
352end 311end
353 312
313
354local function fetch_and_verify_signature_for(url: string, filename: string, tmpdir: string): string, string, string 314local 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
555end 515end
556 516
517function 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
563end
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