diff options
author | V1K1NGbg <victor@ilchev.com> | 2024-08-05 19:41:58 +0300 |
---|---|---|
committer | V1K1NGbg <victor@ilchev.com> | 2024-08-05 20:51:31 +0300 |
commit | e33a230018ef6a8df918d061180ccf8d79921447 (patch) | |
tree | beaadb9ed7060dc26521b3f69d716b3698f16dd4 | |
parent | 515bce044a68283f460b37a08f4c6ec24ec98d53 (diff) | |
download | luarocks-e33a230018ef6a8df918d061180ccf8d79921447.tar.gz luarocks-e33a230018ef6a8df918d061180ccf8d79921447.tar.bz2 luarocks-e33a230018ef6a8df918d061180ccf8d79921447.zip |
core types definition
32 files changed, 1491 insertions, 242 deletions
diff --git a/src/luarocks/core/cfg.d.tl b/src/luarocks/core/cfg.d.tl index 95d3aae7..bbb070f2 100644 --- a/src/luarocks/core/cfg.d.tl +++ b/src/luarocks/core/cfg.d.tl | |||
@@ -1,3 +1,9 @@ | |||
1 | local type rockspec = require("luarocks.core.types.rockspec") | ||
2 | local type Rockspec = rockspec.Rockspec | ||
3 | local type Variables = rockspec.Variables | ||
4 | local type tree = require("luarocks.core.types.tree") | ||
5 | local type Tree = tree.Tree | ||
6 | |||
1 | local record cfg | 7 | local record cfg |
2 | detect_sysconfdir: function(): string | 8 | detect_sysconfdir: function(): string |
3 | make_platforms: function(system: string): {any: boolean} | 9 | make_platforms: function(system: string): {any: boolean} |
@@ -18,136 +24,7 @@ local record cfg | |||
18 | lib_extension: string | 24 | lib_extension: string |
19 | local_cache: string | 25 | local_cache: string |
20 | only_sources_from: string | 26 | only_sources_from: string |
21 | record Tree | ||
22 | root: string | ||
23 | rocks_dir: string | ||
24 | lua_dir: string | ||
25 | lib_dir: string | ||
26 | end | ||
27 | record Description | ||
28 | summary: string | ||
29 | detailed: string | ||
30 | homepage: string | ||
31 | issues_url: string | ||
32 | maintainer: string | ||
33 | license: string | ||
34 | labels: any --! | ||
35 | end | ||
36 | |||
37 | record Variables | ||
38 | HG: string | ||
39 | CVS: string | ||
40 | LUA: string | ||
41 | GPG: string | ||
42 | GIT: string | ||
43 | SVN: string | ||
44 | CURL: string | ||
45 | SSCM: string | ||
46 | PREFIX: string | ||
47 | LUADIR: string | ||
48 | LIBDIR: string | ||
49 | CONFDIR: string | ||
50 | BINDIR: string | ||
51 | DOCDIR: string | ||
52 | CURLNOCERTFLAG: string | ||
53 | end | ||
54 | |||
55 | record Source | ||
56 | url: string | ||
57 | module: string | ||
58 | pathname: string | ||
59 | tag: string | ||
60 | md5: string | ||
61 | file: string | ||
62 | dir: string | ||
63 | branch: string | ||
64 | cvs_tag: string | ||
65 | cvs_module: string | ||
66 | protocol: string --! not in the rockspec definition but used | ||
67 | dir_set: boolean | ||
68 | identifier: string | ||
69 | platforms: any --! | ||
70 | end | ||
71 | |||
72 | record Test | ||
73 | type: string | ||
74 | platforms: any --! {{string: any}}? | ||
75 | end | ||
76 | |||
77 | record Install | ||
78 | lua: any | ||
79 | lib: any | ||
80 | conf: any | ||
81 | bin: any | ||
82 | end | ||
83 | |||
84 | record Build | ||
85 | type: string | ||
86 | modules: string | ||
87 | copy_directories: string | ||
88 | platforms: any --! | ||
89 | install: Install | ||
90 | end | ||
91 | |||
92 | record Dependencie --!1 --? Query?? | ||
93 | |||
94 | end | ||
95 | 27 | ||
96 | record Dependencies | ||
97 | {Dependencie} --!1 | ||
98 | platforms: any --! | ||
99 | end | ||
100 | |||
101 | record BuildDependencies | ||
102 | {Dependencie} --!1 | ||
103 | platforms: any --! | ||
104 | end | ||
105 | |||
106 | record SupportedPlatforms | ||
107 | end | ||
108 | |||
109 | record ExternalDependencies | ||
110 | {Dependencie} --!1 | ||
111 | platforms: any --! | ||
112 | end | ||
113 | |||
114 | record TestDependencies | ||
115 | {Dependencie} --!1 | ||
116 | platforms: any --! | ||
117 | end | ||
118 | |||
119 | record Hooks | ||
120 | post_install: string | ||
121 | platforms: any --! | ||
122 | end | ||
123 | |||
124 | record Deploy | ||
125 | wrap_bin_scripts: boolean | ||
126 | end | ||
127 | |||
128 | record Rockspec | ||
129 | rockspec_format: string | ||
130 | name: string --! not in the rockspec definition but used | ||
131 | package: string | ||
132 | version: string | ||
133 | local_abs_filename: string | ||
134 | rocks_provided: {string : string} | ||
135 | source: Source | ||
136 | description: Description | ||
137 | build: Build | ||
138 | dependencies: Dependencies | ||
139 | build_dependencies: BuildDependencies | ||
140 | test_dependencies: TestDependencies | ||
141 | supported_platforms: SupportedPlatforms | ||
142 | external_dependencies: ExternalDependencies | ||
143 | variables: Variables | ||
144 | hooks: Hooks | ||
145 | test: Test | ||
146 | deploy: Deploy | ||
147 | type: function(Rockspec): string | ||
148 | format_is_at_least: function(Rockspec, string): boolean | ||
149 | end | ||
150 | |||
151 | record cache | 28 | record cache |
152 | luajit_version_checked: boolean | 29 | luajit_version_checked: boolean |
153 | luajit_version: string | 30 | luajit_version: string |
diff --git a/src/luarocks/core/manif.tl b/src/luarocks/core/manif.tl index cfa53dd0..742e64b7 100644 --- a/src/luarocks/core/manif.tl +++ b/src/luarocks/core/manif.tl | |||
@@ -7,35 +7,20 @@ local util = require("luarocks.core.util") | |||
7 | local vers = require("luarocks.core.vers") | 7 | local vers = require("luarocks.core.vers") |
8 | local path = require("luarocks.core.path") | 8 | local path = require("luarocks.core.path") |
9 | 9 | ||
10 | local type Constraint = vers.Constraint | 10 | local type tree = require("luarocks.core.types.tree") |
11 | local type Tree = tree.Tree | ||
11 | 12 | ||
12 | --- Core functions for querying manifest files. | 13 | --- Core functions for querying manifest files. |
13 | local record manif | 14 | local record manif |
14 | |||
15 | record DependencyVersion | ||
16 | constraints: {Constraint} | ||
17 | name: string | ||
18 | end | ||
19 | |||
20 | record Manifest | ||
21 | arch: string | ||
22 | commands: {string: {string}} | ||
23 | dependencies: {string: {string: {DependencyVersion}}} | ||
24 | modules: {string: {string}} | ||
25 | repository: {string: {string: Manifest}} | ||
26 | end | ||
27 | |||
28 | record Tree_manifest | ||
29 | tree: cfg.Tree | ||
30 | manifest: Manifest | ||
31 | end | ||
32 | end | 15 | end |
33 | 16 | ||
34 | -------------------------------------------------------------------------------- | 17 | -------------------------------------------------------------------------------- |
35 | 18 | local type query = require("luarocks.core.types.query") | |
36 | local type DependencyVersion = manif.DependencyVersion | 19 | local type Query = query.Query |
37 | local type Manifest = manif.Manifest | 20 | |
38 | local type Tree_manifest = manif.Tree_manifest | 21 | local type manifest = require("luarocks.core.types.manifest") |
22 | local type Manifest = manifest.Manifest | ||
23 | local type Tree_manifest = manifest.Tree_manifest | ||
39 | 24 | ||
40 | 25 | ||
41 | 26 | ||
@@ -98,7 +83,7 @@ end | |||
98 | 83 | ||
99 | function manif.load_rocks_tree_manifests(deps_mode?: string): {Tree_manifest} | 84 | function manif.load_rocks_tree_manifests(deps_mode?: string): {Tree_manifest} |
100 | local trees = {} | 85 | local trees = {} |
101 | path.map_trees(deps_mode, function(tree: cfg.Tree) | 86 | path.map_trees(deps_mode, function(tree: Tree) |
102 | local manifest= manif.fast_load_local_manifest(path.rocks_dir(tree)) | 87 | local manifest= manif.fast_load_local_manifest(path.rocks_dir(tree)) |
103 | if manifest then | 88 | if manifest then |
104 | table.insert(trees, {tree=tree, manifest=manifest}) | 89 | table.insert(trees, {tree=tree, manifest=manifest}) |
@@ -116,7 +101,7 @@ function manif.scan_dependencies(name: string, version: string, tree_manifests: | |||
116 | for _, tree in ipairs(tree_manifests) do | 101 | for _, tree in ipairs(tree_manifests) do |
117 | local manifest = tree.manifest | 102 | local manifest = tree.manifest |
118 | 103 | ||
119 | local pkgdeps: {DependencyVersion} | 104 | local pkgdeps: {Query} |
120 | if manifest.dependencies and manifest.dependencies[name] then | 105 | if manifest.dependencies and manifest.dependencies[name] then |
121 | pkgdeps = manifest.dependencies[name][version] | 106 | pkgdeps = manifest.dependencies[name][version] |
122 | end | 107 | end |
diff --git a/src/luarocks/core/path.tl b/src/luarocks/core/path.tl index 213c0d69..563a36ef 100644 --- a/src/luarocks/core/path.tl +++ b/src/luarocks/core/path.tl | |||
@@ -5,7 +5,8 @@ end | |||
5 | local cfg = require("luarocks.core.cfg") | 5 | local cfg = require("luarocks.core.cfg") |
6 | local dir = require("luarocks.core.dir") | 6 | local dir = require("luarocks.core.dir") |
7 | 7 | ||
8 | local type Tree = cfg.Tree | 8 | local type tree = require("luarocks.core.types.tree") |
9 | local type Tree = tree.Tree | ||
9 | 10 | ||
10 | local dir_sep = package.config:sub(1, 1) | 11 | local dir_sep = package.config:sub(1, 1) |
11 | -------------------------------------------------------------------------------- | 12 | -------------------------------------------------------------------------------- |
diff --git a/src/luarocks/core/types/manifest.d.tl b/src/luarocks/core/types/manifest.d.tl new file mode 100644 index 00000000..f24869b9 --- /dev/null +++ b/src/luarocks/core/types/manifest.d.tl | |||
@@ -0,0 +1,22 @@ | |||
1 | local type query = require("luarocks.core.types.query") | ||
2 | local type Query = query.Query | ||
3 | |||
4 | local type tree = require("luarocks.core.types.tree") | ||
5 | local type Tree = tree.Tree | ||
6 | |||
7 | local record manifest | ||
8 | record Manifest | ||
9 | arch: string | ||
10 | commands: {string: {string}} | ||
11 | dependencies: {string: {string: {Query}}} | ||
12 | modules: {string: {string}} | ||
13 | repository: {string: {string: {Manifest}}} | ||
14 | end | ||
15 | |||
16 | record Tree_manifest | ||
17 | tree: Tree | ||
18 | manifest: Manifest | ||
19 | end | ||
20 | end | ||
21 | |||
22 | return manifest \ No newline at end of file | ||
diff --git a/src/luarocks/core/types/ordering.d.tl b/src/luarocks/core/types/ordering.d.tl new file mode 100644 index 00000000..c16140f8 --- /dev/null +++ b/src/luarocks/core/types/ordering.d.tl | |||
@@ -0,0 +1,10 @@ | |||
1 | local record ordering | ||
2 | record Ordering<K> | ||
3 | is {K} | ||
4 | sub_orders: {K: Ordering<K>} | ||
5 | end | ||
6 | |||
7 | type SortBy<K> = table.SortFunction<K> | Ordering<K> | ||
8 | end | ||
9 | |||
10 | return ordering \ No newline at end of file | ||
diff --git a/src/luarocks/core/types/query.d.tl b/src/luarocks/core/types/query.d.tl new file mode 100644 index 00000000..e1ef21b6 --- /dev/null +++ b/src/luarocks/core/types/query.d.tl | |||
@@ -0,0 +1,15 @@ | |||
1 | local type version = require("luarocks.core.types.version") | ||
2 | local type Constraint = version.Constraint | ||
3 | |||
4 | local record query | ||
5 | record Query | ||
6 | name: string | ||
7 | namespace: string | ||
8 | constraints: {Constraint} | ||
9 | substring: boolean | ||
10 | arch: {string: boolean} | ||
11 | type: function(): string | ||
12 | end | ||
13 | end | ||
14 | |||
15 | return query \ No newline at end of file | ||
diff --git a/src/luarocks/core/types/rockspec.d.tl b/src/luarocks/core/types/rockspec.d.tl new file mode 100644 index 00000000..438391fa --- /dev/null +++ b/src/luarocks/core/types/rockspec.d.tl | |||
@@ -0,0 +1,124 @@ | |||
1 | local type query = require("luarocks.core.types.query") | ||
2 | local type Query = query.Query | ||
3 | |||
4 | local record rockspec | ||
5 | record Description | ||
6 | summary: string | ||
7 | detailed: string | ||
8 | homepage: string | ||
9 | issues_url: string | ||
10 | maintainer: string | ||
11 | license: string | ||
12 | labels: any --! | ||
13 | end | ||
14 | |||
15 | record Variables | ||
16 | HG: string | ||
17 | CVS: string | ||
18 | LUA: string | ||
19 | GPG: string | ||
20 | GIT: string | ||
21 | SVN: string | ||
22 | CURL: string | ||
23 | SSCM: string | ||
24 | PREFIX: string | ||
25 | LUADIR: string | ||
26 | LIBDIR: string | ||
27 | CONFDIR: string | ||
28 | BINDIR: string | ||
29 | DOCDIR: string | ||
30 | CURLNOCERTFLAG: string | ||
31 | end | ||
32 | |||
33 | record Source | ||
34 | url: string | ||
35 | module: string | ||
36 | pathname: string | ||
37 | tag: string | ||
38 | md5: string | ||
39 | file: string | ||
40 | dir: string | ||
41 | branch: string | ||
42 | cvs_tag: string | ||
43 | cvs_module: string | ||
44 | protocol: string --! not in the rockspec definition but used | ||
45 | dir_set: boolean | ||
46 | identifier: string | ||
47 | end | ||
48 | |||
49 | record Test | ||
50 | type: string | ||
51 | end | ||
52 | |||
53 | record Install | ||
54 | lua: any | ||
55 | lib: any | ||
56 | conf: any | ||
57 | bin: any | ||
58 | end | ||
59 | |||
60 | record Build | ||
61 | type: string | ||
62 | modules: string | ||
63 | copy_directories: string | ||
64 | install: Install | ||
65 | end | ||
66 | |||
67 | record Dependencies | ||
68 | {string} | ||
69 | -- when converted: | ||
70 | queries: {Query} | ||
71 | end | ||
72 | |||
73 | record BuildDependencies | ||
74 | {string} | ||
75 | queries: {Query} | ||
76 | end | ||
77 | |||
78 | record SupportedPlatforms | ||
79 | end | ||
80 | |||
81 | record ExternalDependencies | ||
82 | {string} | ||
83 | queries: {Query} | ||
84 | end | ||
85 | |||
86 | record TestDependencies | ||
87 | {string} | ||
88 | queries: {Query} | ||
89 | end | ||
90 | |||
91 | record Hooks | ||
92 | post_install: string | ||
93 | |||
94 | end | ||
95 | |||
96 | record Deploy | ||
97 | wrap_bin_scripts: boolean | ||
98 | end | ||
99 | |||
100 | record Rockspec | ||
101 | rockspec_format: string | ||
102 | name: string --! not in the rockspec definition but used | ||
103 | package: string | ||
104 | version: string | ||
105 | local_abs_filename: string | ||
106 | rocks_provided: {string : string} | ||
107 | source: Source | ||
108 | description: Description | ||
109 | build: Build | ||
110 | dependencies: Dependencies | ||
111 | build_dependencies: BuildDependencies | ||
112 | test_dependencies: TestDependencies | ||
113 | supported_platforms: SupportedPlatforms | ||
114 | external_dependencies: ExternalDependencies | ||
115 | variables: Variables | ||
116 | hooks: Hooks | ||
117 | test: Test | ||
118 | deploy: Deploy | ||
119 | type: function(): string | ||
120 | format_is_at_least: function(Rockspec, string): boolean | ||
121 | end | ||
122 | end | ||
123 | |||
124 | return rockspec \ No newline at end of file | ||
diff --git a/src/luarocks/core/types/tree.d.tl b/src/luarocks/core/types/tree.d.tl new file mode 100644 index 00000000..df54def9 --- /dev/null +++ b/src/luarocks/core/types/tree.d.tl | |||
@@ -0,0 +1,10 @@ | |||
1 | local record tree | ||
2 | record Tree | ||
3 | root: string | ||
4 | rocks_dir: string | ||
5 | lua_dir: string | ||
6 | lib_dir: string | ||
7 | end | ||
8 | end | ||
9 | |||
10 | return tree \ No newline at end of file | ||
diff --git a/src/luarocks/core/types/version.d.tl b/src/luarocks/core/types/version.d.tl new file mode 100644 index 00000000..92a80996 --- /dev/null +++ b/src/luarocks/core/types/version.d.tl | |||
@@ -0,0 +1,18 @@ | |||
1 | local record version | ||
2 | record Version | ||
3 | is {number} | ||
4 | string: string | ||
5 | revision: number | ||
6 | metamethod __eq: function(Version, Version): boolean | ||
7 | metamethod __lt: function(Version, Version): boolean | ||
8 | metamethod __le: function(Version, Version): boolean | ||
9 | end | ||
10 | |||
11 | record Constraint | ||
12 | op: string | ||
13 | version: Version | string | ||
14 | no_upgrade: boolean | ||
15 | end | ||
16 | end | ||
17 | |||
18 | return version \ No newline at end of file | ||
diff --git a/src/luarocks/core/util.tl b/src/luarocks/core/util.tl index 76d7b42e..ad6d8f9e 100644 --- a/src/luarocks/core/util.tl +++ b/src/luarocks/core/util.tl | |||
@@ -1,16 +1,13 @@ | |||
1 | 1 | ||
2 | local record util | 2 | local record util |
3 | record Ordering<K> | ||
4 | {K} | ||
5 | |||
6 | sub_orders: {K: Ordering<K>} | ||
7 | end | ||
8 | |||
9 | type SortBy<K> = table.SortFunction<K> | util.Ordering<K> | ||
10 | end | 3 | end |
11 | 4 | ||
12 | -------------------------------------------------------------------------------- | 5 | -------------------------------------------------------------------------------- |
13 | 6 | ||
7 | local type ordering = require("luarocks.core.types.ordering") | ||
8 | local type Ordering<K> = ordering.Ordering<K> | ||
9 | local type SortBy<K> = ordering.SortBy<K> | ||
10 | |||
14 | local dir_sep = package.config:sub(1, 1) | 11 | local dir_sep = package.config:sub(1, 1) |
15 | 12 | ||
16 | --- Run a process and read a its output. | 13 | --- Run a process and read a its output. |
@@ -292,9 +289,9 @@ end | |||
292 | -- for that key, which is returned by the iterator as the third value after the key | 289 | -- for that key, which is returned by the iterator as the third value after the key |
293 | -- and the value. | 290 | -- and the value. |
294 | -- @return function: the iterator function. | 291 | -- @return function: the iterator function. |
295 | function util.sortedpairs<K, V>(tbl: {K: V}, sort_by?: util.SortBy<K>): function(): K, V, util.Ordering<K> | 292 | function util.sortedpairs<K, V>(tbl: {K: V}, sort_by?: SortBy<K>): function(): K, V, Ordering<K> |
296 | local keys = util.keys(tbl) | 293 | local keys = util.keys(tbl) |
297 | local sub_orders: {K: util.Ordering<K>} = nil | 294 | local sub_orders: {K: Ordering<K>} = nil |
298 | 295 | ||
299 | if sort_by == nil then | 296 | if sort_by == nil then |
300 | table.sort(keys, default_sort) | 297 | table.sort(keys, default_sort) |
@@ -328,7 +325,7 @@ function util.sortedpairs<K, V>(tbl: {K: V}, sort_by?: util.SortBy<K>): function | |||
328 | end | 325 | end |
329 | 326 | ||
330 | local i = 1 | 327 | local i = 1 |
331 | return function(): K, V, util.Ordering<K> | 328 | return function(): K, V, Ordering<K> |
332 | local key = keys[i] | 329 | local key = keys[i] |
333 | i = i + 1 | 330 | i = i + 1 |
334 | return key, tbl[key], sub_orders and sub_orders[key] | 331 | return key, tbl[key], sub_orders and sub_orders[key] |
diff --git a/src/luarocks/core/vers.tl b/src/luarocks/core/vers.tl index eae6d3d5..ab1c6c5b 100644 --- a/src/luarocks/core/vers.tl +++ b/src/luarocks/core/vers.tl | |||
@@ -1,21 +1,10 @@ | |||
1 | local record vers | 1 | local record vers |
2 | record Version | ||
3 | {number} -- next version of Teal: "is {number}" | ||
4 | string: string | ||
5 | revision: number | ||
6 | metamethod __eq: function(Version, Version): boolean | ||
7 | metamethod __lt: function(Version, Version): boolean | ||
8 | metamethod __le: function(Version, Version): boolean | ||
9 | end | ||
10 | |||
11 | record Constraint | ||
12 | op: string | ||
13 | version: Version | string | ||
14 | no_upgrade: boolean | ||
15 | end | ||
16 | end | 2 | end |
17 | 3 | ||
18 | local util = require("luarocks.core.util") | 4 | local util = require("luarocks.core.util") |
5 | local type version = require("luarocks.core.types.version") | ||
6 | local type Version = version.Version | ||
7 | local type Constraint = version.Constraint | ||
19 | -------------------------------------------------------------------------------- | 8 | -------------------------------------------------------------------------------- |
20 | 9 | ||
21 | local deltas: {string: integer} = { | 10 | local deltas: {string: integer} = { |
@@ -28,9 +17,6 @@ local deltas: {string: integer} = { | |||
28 | alpha = -1000000 | 17 | alpha = -1000000 |
29 | } | 18 | } |
30 | 19 | ||
31 | local type Version = vers.Version | ||
32 | local type Constraint = vers.Constraint | ||
33 | |||
34 | local version_mt: metatable<Version> = { | 20 | local version_mt: metatable<Version> = { |
35 | --- Equality comparison for versions. | 21 | --- Equality comparison for versions. |
36 | -- All version numbers must be equal. | 22 | -- All version numbers must be equal. |
diff --git a/src/luarocks/deps.tl b/src/luarocks/deps.tl new file mode 100644 index 00000000..8fe9feff --- /dev/null +++ b/src/luarocks/deps.tl | |||
@@ -0,0 +1,836 @@ | |||
1 | |||
2 | --- High-level dependency related functions. | ||
3 | local record deps | ||
4 | end | ||
5 | |||
6 | local cfg = require("luarocks.core.cfg") | ||
7 | local manif = require("luarocks.manif") | ||
8 | local path = require("luarocks.path") | ||
9 | local dir = require("luarocks.dir") | ||
10 | local fun = require("luarocks.fun") | ||
11 | local util = require("luarocks.util") | ||
12 | local vers = require("luarocks.core.vers") | ||
13 | local queries = require("luarocks.queries") | ||
14 | local deplocks = require("luarocks.deplocks") | ||
15 | |||
16 | local type rockspec = require("luarocks.core.types.rockspec") | ||
17 | local type Rockspec = rockspec.Rockspec | ||
18 | |||
19 | local type tree = require("luarocks.core.types.tree") | ||
20 | local type Tree = tree.Tree | ||
21 | |||
22 | local core = require("luarocks.core.manif") | ||
23 | local type DependencyVersion = core.DependencyVersion | ||
24 | local type version = require("luarocks.core.types.version") | ||
25 | local type Version = version.Version | ||
26 | |||
27 | --- Generate a function that matches dep queries against the manifest, | ||
28 | -- taking into account rocks_provided, the list of versions to skip, | ||
29 | -- and the lockfile. | ||
30 | -- @param deps_mode "one", "none", "all" or "order" | ||
31 | -- @param rocks_provided a one-level table mapping names to versions, | ||
32 | -- listing rocks to consider provided by the VM | ||
33 | -- @param rocks_provided table: A table of auto-provided dependencies. | ||
34 | -- by this Lua implementation for the given dependency. | ||
35 | -- @param depskey key to use when matching the lockfile ("dependencies", | ||
36 | -- "build_dependencies", etc.) | ||
37 | -- @param skip_set a two-level table mapping names to versions to | ||
38 | -- boolean, listing rocks that should not be matched | ||
39 | -- @return function(dep): {string}, {string:string}, string, boolean | ||
40 | -- * array of matching versions | ||
41 | -- * map of versions to locations | ||
42 | -- * version matched via lockfile if any | ||
43 | -- * true if rock matched via rocks_provided | ||
44 | local function prepare_get_versions(deps_mode: string, rocks_provided: {string : string}, depskey: string, skip_set?): function(DependencyVersion): {string}, {string: string | Tree}, string, boolean | ||
45 | |||
46 | return function(dep: DependencyVersion): {string}, {string: string | Tree}, string, boolean | ||
47 | local versions, locations: {string}, {string: string | Tree} | ||
48 | local provided = rocks_provided[dep.name] | ||
49 | if provided then | ||
50 | -- Provided rocks have higher priority than manifest's rocks. | ||
51 | versions, locations = { provided }, {} | ||
52 | else | ||
53 | if deps_mode == "none" then | ||
54 | deps_mode = "one" | ||
55 | end | ||
56 | versions, locations = manif.get_versions(dep, deps_mode) | ||
57 | end | ||
58 | |||
59 | if skip_set and skip_set[dep.name] then | ||
60 | for i = #versions, 1, -1 do | ||
61 | local v = versions[i] | ||
62 | if skip_set[dep.name][v] then | ||
63 | table.remove(versions, i) | ||
64 | end | ||
65 | end | ||
66 | end | ||
67 | |||
68 | local lockversion = deplocks.get(depskey, dep.name) --! cast? | ||
69 | |||
70 | return versions, locations, lockversion, provided ~= nil | ||
71 | end | ||
72 | end | ||
73 | |||
74 | --- Attempt to match a dependency to an installed rock. | ||
75 | -- @param get_versions a getter function obtained via prepare_get_versions | ||
76 | -- @return (string, string, table) or (nil, nil, table): | ||
77 | -- 1. latest installed version of the rock matching the dependency | ||
78 | -- 2. location where the installed version is installed | ||
79 | -- 3. the 'dep' query table | ||
80 | -- 4. true if provided via VM | ||
81 | -- or | ||
82 | -- 1. nil | ||
83 | -- 2. nil | ||
84 | -- 3. either 'dep' or an alternative query to be used | ||
85 | -- 4. false | ||
86 | local function match_dep(dep: DependencyVersion, | ||
87 | get_versions: function(DependencyVersion): {string}, {string: string | Tree}, string, boolean): string, string | Tree, DependencyVersion, boolean | ||
88 | |||
89 | local versions, locations, lockversion, provided = get_versions(dep) | ||
90 | |||
91 | local latest_version: Version | ||
92 | local latest_vstring: string | ||
93 | for _, vstring in ipairs(versions) do | ||
94 | local version = vers.parse_version(vstring) | ||
95 | if vers.match_constraints(version, dep.constraints) then | ||
96 | if not latest_version or version > latest_version then | ||
97 | latest_version = version | ||
98 | latest_vstring = vstring | ||
99 | end | ||
100 | end | ||
101 | end | ||
102 | |||
103 | if lockversion and not locations[lockversion] then | ||
104 | local latest_matching_msg = "" | ||
105 | if latest_vstring and latest_vstring ~= lockversion then | ||
106 | latest_matching_msg = " (latest matching is " .. latest_vstring .. ")" | ||
107 | end | ||
108 | util.printout("Forcing " .. dep.name .. " to pinned version " .. lockversion .. latest_matching_msg) | ||
109 | return nil, nil, queries.new(dep.name, dep.namespace, lockversion) | ||
110 | end | ||
111 | |||
112 | return latest_vstring, locations[latest_vstring], dep, provided | ||
113 | end | ||
114 | |||
115 | local function match_all_deps(dependencies: {DependencyVersion}, | ||
116 | get_versions: function(DependencyVersion): {string}, {string: string | Tree}, string, boolean): {DependencyVersion: any}, {string}, {string} | ||
117 | |||
118 | local matched, missing, no_upgrade = {}, {}, {} | ||
119 | |||
120 | for _, dep in ipairs(dependencies) do | ||
121 | local found, _, provided: string, string | Tree, boolean | ||
122 | found, _, dep, provided = match_dep(dep, get_versions) | ||
123 | if found then | ||
124 | if not provided then | ||
125 | matched[dep] = {name = dep.name, version = found} | ||
126 | end | ||
127 | else | ||
128 | if dep.constraints[1] and dep.constraints[1].no_upgrade then | ||
129 | no_upgrade[dep.name] = dep | ||
130 | else | ||
131 | missing[dep.name] = dep | ||
132 | end | ||
133 | end | ||
134 | end | ||
135 | return matched, missing, no_upgrade | ||
136 | end | ||
137 | |||
138 | --- Attempt to match dependencies of a rockspec to installed rocks. | ||
139 | -- @param dependencies table: The table of dependencies. | ||
140 | -- @param rocks_provided table: The table of auto-provided dependencies. | ||
141 | -- @param skip_set table or nil: Program versions to not use as valid matches. | ||
142 | -- Table where keys are program names and values are tables where keys | ||
143 | -- are program versions and values are 'true'. | ||
144 | -- @param deps_mode string: Which trees to check dependencies for | ||
145 | -- @return table, table, table: A table where keys are dependencies parsed | ||
146 | -- in table format and values are tables containing fields 'name' and | ||
147 | -- version' representing matches; a table of missing dependencies | ||
148 | -- parsed as tables; and a table of "no-upgrade" missing dependencies | ||
149 | -- (to be used in plugin modules so that a plugin does not force upgrade of | ||
150 | -- its parent application). | ||
151 | function deps.match_deps(dependencies, rocks_provided, skip_set, deps_mode) | ||
152 | assert(type(dependencies) == "table") | ||
153 | assert(type(rocks_provided) == "table") | ||
154 | assert(type(skip_set) == "table" or skip_set == nil) | ||
155 | assert(type(deps_mode) == "string") | ||
156 | |||
157 | local get_versions = prepare_get_versions(deps_mode, rocks_provided, "dependencies", skip_set) | ||
158 | return match_all_deps(dependencies, get_versions) | ||
159 | end | ||
160 | |||
161 | local function rock_status(dep, get_versions) | ||
162 | assert(dep:type() == "query") | ||
163 | assert(type(get_versions) == "function") | ||
164 | |||
165 | local installed, _, _, provided = match_dep(dep, get_versions) | ||
166 | local installation_type = provided and "provided by VM" or "installed" | ||
167 | return installed and installed.." "..installation_type..": success" or "not installed" | ||
168 | end | ||
169 | |||
170 | --- Check depenendencies of a package and report any missing ones. | ||
171 | -- @param name string: package name. | ||
172 | -- @param version string: package version. | ||
173 | -- @param dependencies table: array of dependencies. | ||
174 | -- @param deps_mode string: Which trees to check dependencies for | ||
175 | -- @param rocks_provided table: A table of auto-dependencies provided | ||
176 | -- by this Lua implementation for the given dependency. | ||
177 | -- "one" for the current default tree, "all" for all trees, | ||
178 | -- "order" for all trees with priority >= the current default, "none" for no trees. | ||
179 | function deps.report_missing_dependencies(name, version, dependencies, deps_mode, rocks_provided) | ||
180 | assert(type(name) == "string") | ||
181 | assert(type(version) == "string") | ||
182 | assert(type(dependencies) == "table") | ||
183 | assert(type(deps_mode) == "string") | ||
184 | assert(type(rocks_provided) == "table") | ||
185 | |||
186 | if deps_mode == "none" then | ||
187 | return | ||
188 | end | ||
189 | |||
190 | local get_versions = prepare_get_versions(deps_mode, rocks_provided, "dependencies") | ||
191 | |||
192 | local first_missing_dep = true | ||
193 | |||
194 | for _, dep in ipairs(dependencies) do | ||
195 | local found, _ | ||
196 | found, _, dep = match_dep(dep, get_versions) | ||
197 | if not found then | ||
198 | if first_missing_dep then | ||
199 | util.printout(("Missing dependencies for %s %s:"):format(name, version)) | ||
200 | first_missing_dep = false | ||
201 | end | ||
202 | |||
203 | util.printout((" %s (%s)"):format(tostring(dep), rock_status(dep, get_versions))) | ||
204 | end | ||
205 | end | ||
206 | end | ||
207 | |||
208 | function deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey) | ||
209 | assert(dep:type() == "query") | ||
210 | assert(type(deps_mode) == "string" or deps_mode == nil) | ||
211 | assert(type(rocks_provided) == "table" or rocks_provided == nil) | ||
212 | assert(type(verify) == "boolean" or verify == nil) | ||
213 | assert(type(depskey) == "string") | ||
214 | |||
215 | deps_mode = deps_mode or "all" | ||
216 | rocks_provided = rocks_provided or {} | ||
217 | |||
218 | local get_versions = prepare_get_versions(deps_mode, rocks_provided, depskey) | ||
219 | |||
220 | local found, where | ||
221 | found, where, dep = match_dep(dep, get_versions) | ||
222 | if found then | ||
223 | local tree_manifests = manif.load_rocks_tree_manifests(deps_mode) | ||
224 | manif.scan_dependencies(dep.name, found, tree_manifests, deplocks.proxy(depskey)) | ||
225 | return true, found, where | ||
226 | end | ||
227 | |||
228 | local search = require("luarocks.search") | ||
229 | local install = require("luarocks.cmd.install") | ||
230 | |||
231 | local url, search_err = search.find_suitable_rock(dep) | ||
232 | if not url then | ||
233 | return nil, "Could not satisfy dependency "..tostring(dep)..": "..search_err | ||
234 | end | ||
235 | util.printout("Installing "..url) | ||
236 | local install_args = { | ||
237 | rock = url, | ||
238 | deps_mode = deps_mode, | ||
239 | namespace = dep.namespace, | ||
240 | verify = verify, | ||
241 | } | ||
242 | local ok, install_err, errcode = install.command(install_args) | ||
243 | if not ok then | ||
244 | return nil, "Failed installing dependency: "..url.." - "..install_err, errcode | ||
245 | end | ||
246 | |||
247 | found, where = match_dep(dep, get_versions) | ||
248 | assert(found) | ||
249 | return true, found, where | ||
250 | end | ||
251 | |||
252 | local function check_supported_platforms(rockspec) | ||
253 | if rockspec.supported_platforms and next(rockspec.supported_platforms) then | ||
254 | local all_negative = true | ||
255 | local supported = false | ||
256 | for _, plat in pairs(rockspec.supported_platforms) do | ||
257 | local neg | ||
258 | neg, plat = plat:match("^(!?)(.*)") | ||
259 | if neg == "!" then | ||
260 | if cfg.is_platform(plat) then | ||
261 | return nil, "This rockspec for "..rockspec.package.." does not support "..plat.." platforms." | ||
262 | end | ||
263 | else | ||
264 | all_negative = false | ||
265 | if cfg.is_platform(plat) then | ||
266 | supported = true | ||
267 | break | ||
268 | end | ||
269 | end | ||
270 | end | ||
271 | if supported == false and not all_negative then | ||
272 | local plats = cfg.print_platforms() | ||
273 | return nil, "This rockspec for "..rockspec.package.." does not support "..plats.." platforms." | ||
274 | end | ||
275 | end | ||
276 | |||
277 | return true | ||
278 | end | ||
279 | |||
280 | --- Check dependencies of a rock and attempt to install any missing ones. | ||
281 | -- Packages are installed using the LuaRocks "install" command. | ||
282 | -- Aborts the program if a dependency could not be fulfilled. | ||
283 | -- @param rockspec table: A rockspec in table format. | ||
284 | -- @param depskey string: Rockspec key to fetch to get dependency table | ||
285 | -- ("dependencies", "build_dependencies", etc.). | ||
286 | -- @param deps_mode string | ||
287 | -- @param verify boolean | ||
288 | -- @param deplock_dir string: dirname of the deplock file | ||
289 | -- @return boolean or (nil, string, [string]): True if no errors occurred, or | ||
290 | -- nil and an error message if any test failed, followed by an optional | ||
291 | -- error code. | ||
292 | function deps.fulfill_dependencies(rockspec, depskey, deps_mode, verify, deplock_dir) | ||
293 | assert(type(rockspec) == "table") | ||
294 | assert(type(depskey) == "string") | ||
295 | assert(type(deps_mode) == "string") | ||
296 | assert(type(verify) == "boolean" or verify == nil) | ||
297 | assert(type(deplock_dir) == "string" or deplock_dir == nil) | ||
298 | |||
299 | local name = rockspec.name | ||
300 | local version = rockspec.version | ||
301 | local rocks_provided = rockspec.rocks_provided | ||
302 | |||
303 | local ok, filename, err = deplocks.load(name, deplock_dir or ".") | ||
304 | if filename then | ||
305 | util.printout("Using dependencies pinned in lockfile: " .. filename) | ||
306 | |||
307 | local get_versions = prepare_get_versions("none", rocks_provided, depskey) | ||
308 | for dnsname, dversion in deplocks.each(depskey) do | ||
309 | local dname, dnamespace = util.split_namespace(dnsname) | ||
310 | local dep = queries.new(dname, dnamespace, dversion) | ||
311 | |||
312 | util.printout(("%s %s is pinned to %s (%s)"):format( | ||
313 | name, version, tostring(dep), rock_status(dep, get_versions))) | ||
314 | |||
315 | local ok, err = deps.fulfill_dependency(dep, "none", rocks_provided, verify, depskey) | ||
316 | if not ok then | ||
317 | return nil, err | ||
318 | end | ||
319 | end | ||
320 | util.printout() | ||
321 | return true | ||
322 | elseif err then | ||
323 | util.warning(err) | ||
324 | end | ||
325 | |||
326 | ok, err = check_supported_platforms(rockspec) | ||
327 | if not ok then | ||
328 | return nil, err | ||
329 | end | ||
330 | |||
331 | deps.report_missing_dependencies(name, version, rockspec[depskey], deps_mode, rocks_provided) | ||
332 | |||
333 | util.printout() | ||
334 | |||
335 | local get_versions = prepare_get_versions(deps_mode, rocks_provided, depskey) | ||
336 | for _, dep in ipairs(rockspec[depskey]) do | ||
337 | |||
338 | util.printout(("%s %s depends on %s (%s)"):format( | ||
339 | name, version, tostring(dep), rock_status(dep, get_versions))) | ||
340 | |||
341 | local ok, found_or_err, _, no_upgrade = deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey) | ||
342 | if ok then | ||
343 | deplocks.add(depskey, dep.name, found_or_err) | ||
344 | else | ||
345 | if no_upgrade then | ||
346 | util.printerr("This version of "..name.." is designed for use with") | ||
347 | util.printerr(tostring(dep)..", but is configured to avoid upgrading it") | ||
348 | util.printerr("automatically. Please upgrade "..dep.name.." with") | ||
349 | util.printerr(" luarocks install "..dep.name) | ||
350 | util.printerr("or look for a suitable version of "..name.." with") | ||
351 | util.printerr(" luarocks search "..name) | ||
352 | end | ||
353 | return nil, found_or_err | ||
354 | end | ||
355 | end | ||
356 | |||
357 | return true | ||
358 | end | ||
359 | |||
360 | --- If filename matches a pattern, return the capture. | ||
361 | -- For example, given "libfoo.so" and "lib?.so" is a pattern, | ||
362 | -- returns "foo" (which can then be used to build names | ||
363 | -- based on other patterns. | ||
364 | -- @param file string: a filename | ||
365 | -- @param pattern string: a pattern, where ? is to be matched by the filename. | ||
366 | -- @return string The pattern, if found, or nil. | ||
367 | local function deconstruct_pattern(file, pattern) | ||
368 | local depattern = "^"..(pattern:gsub("%.", "%%."):gsub("%*", ".*"):gsub("?", "(.*)")).."$" | ||
369 | return (file:match(depattern)) | ||
370 | end | ||
371 | |||
372 | --- Construct all possible patterns for a name and add to the files array. | ||
373 | -- Run through the patterns array replacing all occurrences of "?" | ||
374 | -- with the given file name and store them in the files array. | ||
375 | -- @param file string A raw name (e.g. "foo") | ||
376 | -- @param array of string An array of patterns with "?" as the wildcard | ||
377 | -- (e.g. {"?.so", "lib?.so"}) | ||
378 | -- @param files The array of constructed names | ||
379 | local function add_all_patterns(file, patterns, files) | ||
380 | for _, pattern in ipairs(patterns) do | ||
381 | table.insert(files, {#files + 1, (pattern:gsub("?", file))}) | ||
382 | end | ||
383 | end | ||
384 | |||
385 | local function get_external_deps_dirs(mode) | ||
386 | local patterns = cfg.external_deps_patterns | ||
387 | local subdirs = cfg.external_deps_subdirs | ||
388 | if mode == "install" then | ||
389 | patterns = cfg.runtime_external_deps_patterns | ||
390 | subdirs = cfg.runtime_external_deps_subdirs | ||
391 | end | ||
392 | local dirs = { | ||
393 | BINDIR = { subdir = subdirs.bin, testfile = "program", pattern = patterns.bin }, | ||
394 | INCDIR = { subdir = subdirs.include, testfile = "header", pattern = patterns.include }, | ||
395 | LIBDIR = { subdir = subdirs.lib, testfile = "library", pattern = patterns.lib } | ||
396 | } | ||
397 | if mode == "install" then | ||
398 | dirs.INCDIR = nil | ||
399 | end | ||
400 | return dirs | ||
401 | end | ||
402 | |||
403 | local function resolve_prefix(prefix, dirs) | ||
404 | if type(prefix) == "string" then | ||
405 | return prefix | ||
406 | elseif type(prefix) == "table" then | ||
407 | if prefix.bin then | ||
408 | dirs.BINDIR.subdir = prefix.bin | ||
409 | end | ||
410 | if prefix.include then | ||
411 | if dirs.INCDIR then | ||
412 | dirs.INCDIR.subdir = prefix.include | ||
413 | end | ||
414 | end | ||
415 | if prefix.lib then | ||
416 | dirs.LIBDIR.subdir = prefix.lib | ||
417 | end | ||
418 | return prefix.prefix | ||
419 | end | ||
420 | end | ||
421 | |||
422 | local function add_patterns_for_file(files, file, patterns) | ||
423 | -- If it doesn't look like it contains a filename extension | ||
424 | if not (file:match("%.[a-z]+$") or file:match("%.[a-z]+%.")) then | ||
425 | add_all_patterns(file, patterns, files) | ||
426 | else | ||
427 | for _, pattern in ipairs(patterns) do | ||
428 | local matched = deconstruct_pattern(file, pattern) | ||
429 | if matched then | ||
430 | add_all_patterns(matched, patterns, files) | ||
431 | end | ||
432 | end | ||
433 | table.insert(files, {#files + 1, file}) | ||
434 | end | ||
435 | end | ||
436 | |||
437 | local function check_external_dependency_at(prefix, name, ext_files, vars, dirs, err_files, cache) | ||
438 | local fs = require("luarocks.fs") | ||
439 | cache = cache or {} | ||
440 | |||
441 | for dirname, dirdata in util.sortedpairs(dirs) do | ||
442 | local paths | ||
443 | local path_var_value = vars[name.."_"..dirname] | ||
444 | if path_var_value then | ||
445 | paths = { path_var_value } | ||
446 | elseif type(dirdata.subdir) == "table" then | ||
447 | paths = {} | ||
448 | for i,v in ipairs(dirdata.subdir) do | ||
449 | paths[i] = dir.path(prefix, v) | ||
450 | end | ||
451 | else | ||
452 | paths = { dir.path(prefix, dirdata.subdir) } | ||
453 | end | ||
454 | local file_or_files = ext_files[dirdata.testfile] | ||
455 | if file_or_files then | ||
456 | local files = {} | ||
457 | if type(file_or_files) == "string" then | ||
458 | add_patterns_for_file(files, file_or_files, dirdata.pattern) | ||
459 | elseif type(file_or_files) == "table" then | ||
460 | for _, f in ipairs(file_or_files) do | ||
461 | add_patterns_for_file(files, f, dirdata.pattern) | ||
462 | end | ||
463 | end | ||
464 | |||
465 | local found = false | ||
466 | table.sort(files, function(a, b) | ||
467 | if (not a[2]:match("%*")) and b[2]:match("%*") then | ||
468 | return true | ||
469 | elseif a[2]:match("%*") and (not b[2]:match("%*")) then | ||
470 | return false | ||
471 | else | ||
472 | return a[1] < b[1] | ||
473 | end | ||
474 | end) | ||
475 | for _, fa in ipairs(files) do | ||
476 | |||
477 | local f = fa[2] | ||
478 | -- small convenience hack | ||
479 | if f:match("%.so$") or f:match("%.dylib$") or f:match("%.dll$") then | ||
480 | f = f:gsub("%.[^.]+$", "."..cfg.external_lib_extension) | ||
481 | end | ||
482 | |||
483 | local pattern | ||
484 | if f:match("%*") then | ||
485 | pattern = "^" .. f:gsub("([-.+])", "%%%1"):gsub("%*", ".*") .. "$" | ||
486 | f = "matching "..f | ||
487 | end | ||
488 | |||
489 | for _, d in ipairs(paths) do | ||
490 | if pattern then | ||
491 | if not cache[d] then | ||
492 | cache[d] = fs.list_dir(d) | ||
493 | end | ||
494 | local match = string.match | ||
495 | for _, entry in ipairs(cache[d]) do | ||
496 | if match(entry, pattern) then | ||
497 | found = true | ||
498 | break | ||
499 | end | ||
500 | end | ||
501 | else | ||
502 | found = fs.is_file(dir.path(d, f)) | ||
503 | end | ||
504 | if found then | ||
505 | dirdata.dir = d | ||
506 | dirdata.file = f | ||
507 | break | ||
508 | else | ||
509 | table.insert(err_files[dirdata.testfile], f.." in "..d) | ||
510 | end | ||
511 | end | ||
512 | if found then | ||
513 | break | ||
514 | end | ||
515 | end | ||
516 | if not found then | ||
517 | return nil, dirname, dirdata.testfile | ||
518 | end | ||
519 | else | ||
520 | -- When we have a set of subdir suffixes, look for one that exists. | ||
521 | -- For these reason, we now put "lib" ahead of "" on Windows in our | ||
522 | -- default set. | ||
523 | dirdata.dir = paths[1] | ||
524 | for _, p in ipairs(paths) do | ||
525 | if fs.exists(p) then | ||
526 | dirdata.dir = p | ||
527 | break | ||
528 | end | ||
529 | end | ||
530 | end | ||
531 | end | ||
532 | |||
533 | for dirname, dirdata in pairs(dirs) do | ||
534 | vars[name.."_"..dirname] = dirdata.dir | ||
535 | vars[name.."_"..dirname.."_FILE"] = dirdata.file | ||
536 | end | ||
537 | vars[name.."_DIR"] = prefix | ||
538 | return true | ||
539 | end | ||
540 | |||
541 | local function check_external_dependency(name, ext_files, vars, mode, cache) | ||
542 | local ok | ||
543 | local err_dirname | ||
544 | local err_testfile | ||
545 | local err_files = {program = {}, header = {}, library = {}} | ||
546 | |||
547 | local dirs = get_external_deps_dirs(mode) | ||
548 | |||
549 | local prefixes | ||
550 | if vars[name .. "_DIR"] then | ||
551 | prefixes = { vars[name .. "_DIR"] } | ||
552 | elseif vars.DEPS_DIR then | ||
553 | prefixes = { vars.DEPS_DIR } | ||
554 | else | ||
555 | prefixes = cfg.external_deps_dirs | ||
556 | end | ||
557 | |||
558 | for _, prefix in ipairs(prefixes) do | ||
559 | prefix = resolve_prefix(prefix, dirs) | ||
560 | if cfg.is_platform("mingw32") and name == "LUA" then | ||
561 | dirs.LIBDIR.pattern = fun.filter(util.deep_copy(dirs.LIBDIR.pattern), function(s) | ||
562 | return not s:match("%.a$") | ||
563 | end) | ||
564 | elseif cfg.is_platform("windows") and name == "LUA" then | ||
565 | dirs.LIBDIR.pattern = fun.filter(util.deep_copy(dirs.LIBDIR.pattern), function(s) | ||
566 | return not s:match("%.dll$") | ||
567 | end) | ||
568 | end | ||
569 | ok, err_dirname, err_testfile = check_external_dependency_at(prefix, name, ext_files, vars, dirs, err_files, cache) | ||
570 | if ok then | ||
571 | return true | ||
572 | end | ||
573 | end | ||
574 | |||
575 | return nil, err_dirname, err_testfile, err_files | ||
576 | end | ||
577 | |||
578 | function deps.autodetect_external_dependencies(build) | ||
579 | -- only applies to the 'builtin' build type | ||
580 | if not build or not build.modules then | ||
581 | return nil | ||
582 | end | ||
583 | |||
584 | local extdeps = {} | ||
585 | local any = false | ||
586 | for _, data in pairs(build.modules) do | ||
587 | if type(data) == "table" and data.libraries then | ||
588 | local libraries = data.libraries | ||
589 | if type(libraries) == "string" then | ||
590 | libraries = { libraries } | ||
591 | end | ||
592 | local incdirs = {} | ||
593 | local libdirs = {} | ||
594 | for _, lib in ipairs(libraries) do | ||
595 | local upper = lib:upper():gsub("%+", "P"):gsub("[^%w]", "_") | ||
596 | any = true | ||
597 | extdeps[upper] = { library = lib } | ||
598 | table.insert(incdirs, "$(" .. upper .. "_INCDIR)") | ||
599 | table.insert(libdirs, "$(" .. upper .. "_LIBDIR)") | ||
600 | end | ||
601 | if not data.incdirs then | ||
602 | data.incdirs = incdirs | ||
603 | end | ||
604 | if not data.libdirs then | ||
605 | data.libdirs = libdirs | ||
606 | end | ||
607 | end | ||
608 | end | ||
609 | return any and extdeps or nil | ||
610 | end | ||
611 | |||
612 | --- Set up path-related variables for external dependencies. | ||
613 | -- For each key in the external_dependencies table in the | ||
614 | -- rockspec file, four variables are created: <key>_DIR, <key>_BINDIR, | ||
615 | -- <key>_INCDIR and <key>_LIBDIR. These are not overwritten | ||
616 | -- if already set (e.g. by the LuaRocks config file or through the | ||
617 | -- command-line). Values in the external_dependencies table | ||
618 | -- are tables that may contain a "header" or a "library" field, | ||
619 | -- with filenames to be tested for existence. | ||
620 | -- @param rockspec table: The rockspec table. | ||
621 | -- @param mode string: if "build" is given, checks all files; | ||
622 | -- if "install" is given, do not scan for headers. | ||
623 | -- @return boolean or (nil, string): True if no errors occurred, or | ||
624 | -- nil and an error message if any test failed. | ||
625 | function deps.check_external_deps(rockspec, mode) | ||
626 | |||
627 | if not rockspec.external_dependencies then | ||
628 | rockspec.external_dependencies = deps.autodetect_external_dependencies(rockspec.build) | ||
629 | end | ||
630 | if not rockspec.external_dependencies then | ||
631 | return true | ||
632 | end | ||
633 | |||
634 | for name, ext_files in util.sortedpairs(rockspec.external_dependencies) do | ||
635 | local ok, err_dirname, err_testfile, err_files = check_external_dependency(name, ext_files, rockspec.variables, mode) | ||
636 | if not ok then | ||
637 | local lines = {"Could not find "..err_testfile.." file for "..name} | ||
638 | |||
639 | local err_paths = {} | ||
640 | for _, err_file in ipairs(err_files[err_testfile]) do | ||
641 | if not err_paths[err_file] then | ||
642 | err_paths[err_file] = true | ||
643 | table.insert(lines, " No file "..err_file) | ||
644 | end | ||
645 | end | ||
646 | |||
647 | table.insert(lines, "You may have to install "..name.." in your system and/or pass "..name.."_DIR or "..name.."_"..err_dirname.." to the luarocks command.") | ||
648 | table.insert(lines, "Example: luarocks install "..rockspec.name.." "..name.."_DIR=/usr/local") | ||
649 | |||
650 | return nil, table.concat(lines, "\n"), "dependency" | ||
651 | end | ||
652 | end | ||
653 | return true | ||
654 | end | ||
655 | |||
656 | --- Recursively add satisfied dependencies of a package to a table, | ||
657 | -- to build a transitive closure of all dependent packages. | ||
658 | -- Additionally ensures that `dependencies` table of the manifest is up-to-date. | ||
659 | -- @param results table: The results table being built, maps package names to versions. | ||
660 | -- @param mdeps table: The manifest dependencies table. | ||
661 | -- @param name string: Package name. | ||
662 | -- @param version string: Package version. | ||
663 | function deps.scan_deps(results, mdeps, name, version, deps_mode) | ||
664 | assert(type(results) == "table") | ||
665 | assert(type(mdeps) == "table") | ||
666 | assert(type(name) == "string" and not name:match("/")) | ||
667 | assert(type(version) == "string") | ||
668 | |||
669 | local fetch = require("luarocks.fetch") | ||
670 | |||
671 | if results[name] then | ||
672 | return | ||
673 | end | ||
674 | if not mdeps[name] then mdeps[name] = {} end | ||
675 | local mdn = mdeps[name] | ||
676 | local dependencies = mdn[version] | ||
677 | local rocks_provided | ||
678 | if not dependencies then | ||
679 | local rockspec, err = fetch.load_local_rockspec(path.rockspec_file(name, version), false) | ||
680 | if not rockspec then | ||
681 | return | ||
682 | end | ||
683 | dependencies = rockspec.dependencies | ||
684 | rocks_provided = rockspec.rocks_provided | ||
685 | mdn[version] = dependencies | ||
686 | else | ||
687 | rocks_provided = util.get_rocks_provided() | ||
688 | end | ||
689 | |||
690 | local get_versions = prepare_get_versions(deps_mode, rocks_provided, "dependencies") | ||
691 | |||
692 | local matched = match_all_deps(dependencies, get_versions) | ||
693 | results[name] = version | ||
694 | for _, match in pairs(matched) do | ||
695 | deps.scan_deps(results, mdeps, match.name, match.version, deps_mode) | ||
696 | end | ||
697 | end | ||
698 | |||
699 | local function lua_h_exists(d, luaver) | ||
700 | local major, minor = luaver:match("(%d+)%.(%d+)") | ||
701 | local luanum = ("%s%02d"):format(major, tonumber(minor)) | ||
702 | |||
703 | local lua_h = dir.path(d, "lua.h") | ||
704 | local fd = io.open(lua_h) | ||
705 | if fd then | ||
706 | local data = fd:read("*a") | ||
707 | fd:close() | ||
708 | if data:match("LUA_VERSION_NUM%s*" .. tostring(luanum)) then | ||
709 | return d | ||
710 | end | ||
711 | return nil, "Lua header lua.h found at " .. d .. " does not match Lua version " .. luaver .. ". You can use `luarocks config variables.LUA_INCDIR <path>` to set the correct location.", "dependency", 2 | ||
712 | end | ||
713 | |||
714 | return nil, "Failed finding Lua header lua.h (searched at " .. d .. "). You may need to install Lua development headers. You can use `luarocks config variables.LUA_INCDIR <path>` to set the correct location.", "dependency", 1 | ||
715 | end | ||
716 | |||
717 | local function find_lua_incdir(prefix, luaver, luajitver) | ||
718 | luajitver = luajitver and luajitver:gsub("%-.*", "") | ||
719 | local shortv = luaver:gsub("%.", "") | ||
720 | local incdirs = { | ||
721 | prefix .. "/include/lua/" .. luaver, | ||
722 | prefix .. "/include/lua" .. luaver, | ||
723 | prefix .. "/include/lua-" .. luaver, | ||
724 | prefix .. "/include/lua" .. shortv, | ||
725 | prefix .. "/include", | ||
726 | prefix, | ||
727 | luajitver and (prefix .. "/include/luajit-" .. (luajitver:match("^(%d+%.%d+)") or "")), | ||
728 | } | ||
729 | local errprio = 0 | ||
730 | local mainerr | ||
731 | for _, d in ipairs(incdirs) do | ||
732 | local ok, err, _, prio = lua_h_exists(d, luaver) | ||
733 | if ok then | ||
734 | return d | ||
735 | end | ||
736 | if prio > errprio then | ||
737 | mainerr = err | ||
738 | errprio = prio | ||
739 | end | ||
740 | end | ||
741 | |||
742 | -- not found, will fallback to a default | ||
743 | return nil, mainerr | ||
744 | end | ||
745 | |||
746 | function deps.check_lua_incdir(vars) | ||
747 | if vars.LUA_INCDIR_OK == true | ||
748 | then return true | ||
749 | end | ||
750 | |||
751 | local ljv = util.get_luajit_version() | ||
752 | |||
753 | if vars.LUA_INCDIR then | ||
754 | local ok, err = lua_h_exists(vars.LUA_INCDIR, cfg.lua_version) | ||
755 | if ok then | ||
756 | vars.LUA_INCDIR_OK = true | ||
757 | end | ||
758 | return ok, err | ||
759 | end | ||
760 | |||
761 | if vars.LUA_DIR then | ||
762 | local d, err = find_lua_incdir(vars.LUA_DIR, cfg.lua_version, ljv) | ||
763 | if d then | ||
764 | vars.LUA_INCDIR = d | ||
765 | vars.LUA_INCDIR_OK = true | ||
766 | return true | ||
767 | end | ||
768 | return nil, err | ||
769 | end | ||
770 | |||
771 | return nil, "Failed finding Lua headers; neither LUA_DIR or LUA_INCDIR are set. You may need to install them or configure LUA_INCDIR.", "dependency" | ||
772 | end | ||
773 | |||
774 | function deps.check_lua_libdir(vars) | ||
775 | if vars.LUA_LIBDIR_OK == true | ||
776 | then return true | ||
777 | end | ||
778 | |||
779 | local fs = require("luarocks.fs") | ||
780 | local ljv = util.get_luajit_version() | ||
781 | |||
782 | if vars.LUA_LIBDIR and vars.LUALIB and fs.exists(dir.path(vars.LUA_LIBDIR, vars.LUALIB)) then | ||
783 | vars.LUA_LIBDIR_OK = true | ||
784 | return true | ||
785 | end | ||
786 | |||
787 | local shortv = cfg.lua_version:gsub("%.", "") | ||
788 | local libnames = { | ||
789 | "lua" .. cfg.lua_version, | ||
790 | "lua" .. shortv, | ||
791 | "lua-" .. cfg.lua_version, | ||
792 | "lua-" .. shortv, | ||
793 | "lua", | ||
794 | } | ||
795 | if ljv then | ||
796 | table.insert(libnames, 1, "luajit-" .. cfg.lua_version) | ||
797 | table.insert(libnames, 2, "luajit") | ||
798 | end | ||
799 | local cache = {} | ||
800 | local save_LUA_INCDIR = vars.LUA_INCDIR | ||
801 | local ok, _, _, errfiles = check_external_dependency("LUA", { library = libnames }, vars, "build", cache) | ||
802 | vars.LUA_INCDIR = save_LUA_INCDIR | ||
803 | local err | ||
804 | if ok then | ||
805 | local filename = dir.path(vars.LUA_LIBDIR, vars.LUA_LIBDIR_FILE) | ||
806 | local fd = io.open(filename, "r") | ||
807 | if fd then | ||
808 | if not vars.LUA_LIBDIR_FILE:match((cfg.lua_version:gsub("%.", "%%.?"))) then | ||
809 | -- if filename isn't versioned, check file contents | ||
810 | local txt = fd:read("*a") | ||
811 | ok = txt:match("Lua " .. cfg.lua_version, 1, true) | ||
812 | or txt:match("lua" .. (cfg.lua_version:gsub("%.", "")), 1, true) | ||
813 | if not ok then | ||
814 | err = "Lua library at " .. filename .. " does not match Lua version " .. cfg.lua_version .. ". You can use `luarocks config variables.LUA_LIBDIR <path>` to set the correct location." | ||
815 | end | ||
816 | end | ||
817 | |||
818 | fd:close() | ||
819 | end | ||
820 | end | ||
821 | |||
822 | if ok then | ||
823 | vars.LUALIB = vars.LUA_LIBDIR_FILE | ||
824 | vars.LUA_LIBDIR_OK = true | ||
825 | return true | ||
826 | else | ||
827 | err = err or "Failed finding the Lua library. You can use `luarocks config variables.LUA_LIBDIR <path>` to set the correct location." | ||
828 | return nil, err, "dependency", errfiles | ||
829 | end | ||
830 | end | ||
831 | |||
832 | function deps.get_deps_mode(args) | ||
833 | return args.deps_mode or cfg.deps_mode | ||
834 | end | ||
835 | |||
836 | return deps | ||
diff --git a/src/luarocks/fetch.tl b/src/luarocks/fetch.tl index 6434edac..4c126575 100644 --- a/src/luarocks/fetch.tl +++ b/src/luarocks/fetch.tl | |||
@@ -13,7 +13,8 @@ local util = require("luarocks.util") | |||
13 | local cfg = require("luarocks.core.cfg") | 13 | local cfg = require("luarocks.core.cfg") |
14 | 14 | ||
15 | local type Lock = fs.Lock --! | 15 | local type Lock = fs.Lock --! |
16 | local type Rockspec = cfg.Rockspec | 16 | local type rockspec = require("luarocks.core.types.rockspec") |
17 | local type Rockspec = rockspec.Rockspec | ||
17 | 18 | ||
18 | 19 | ||
19 | local function ensure_trailing_slash(url: string): string | 20 | local function ensure_trailing_slash(url: string): string |
@@ -517,7 +518,6 @@ end | |||
517 | -- the fetched source tarball and the temporary directory created to | 518 | -- the fetched source tarball and the temporary directory created to |
518 | -- store it; or nil and an error message and optional error code. | 519 | -- store it; or nil and an error message and optional error code. |
519 | function fetch.get_sources(rockspec: Rockspec, extract: boolean, dest_dir?: string): string, string, string | 520 | function fetch.get_sources(rockspec: Rockspec, extract: boolean, dest_dir?: string): string, string, string |
520 | -- assert(rockspec:type() == "rockspec") --! | ||
521 | 521 | ||
522 | local url = rockspec.source.url | 522 | local url = rockspec.source.url |
523 | local name = rockspec.name.."-"..rockspec.version | 523 | local name = rockspec.name.."-"..rockspec.version |
@@ -563,7 +563,6 @@ end | |||
563 | -- the fetched source tarball and the temporary directory created to | 563 | -- the fetched source tarball and the temporary directory created to |
564 | -- store it; or nil and an error message. | 564 | -- store it; or nil and an error message. |
565 | function fetch.fetch_sources(rockspec: Rockspec, extract: string, dest_dir?: string): string, string, string, string, string | 565 | function fetch.fetch_sources(rockspec: Rockspec, extract: string, dest_dir?: string): string, string, string, string, string |
566 | assert(rockspec:type() == "rockspec") --! | ||
567 | 566 | ||
568 | -- auto-convert git://github.com URLs to use git+https | 567 | -- auto-convert git://github.com URLs to use git+https |
569 | -- see https://github.blog/2021-09-01-improving-git-protocol-security-github/ | 568 | -- see https://github.blog/2021-09-01-improving-git-protocol-security-github/ |
diff --git a/src/luarocks/fetch/cvs.tl b/src/luarocks/fetch/cvs.tl index 60f55957..f40d0991 100644 --- a/src/luarocks/fetch/cvs.tl +++ b/src/luarocks/fetch/cvs.tl | |||
@@ -6,9 +6,9 @@ end | |||
6 | local fs = require("luarocks.fs") | 6 | local fs = require("luarocks.fs") |
7 | local dir = require("luarocks.dir") | 7 | local dir = require("luarocks.dir") |
8 | local util = require("luarocks.util") | 8 | local util = require("luarocks.util") |
9 | local cfg = require("luarocks.core.cfg") --! import for Rockspec | ||
10 | 9 | ||
11 | local type Rockspec = cfg.Rockspec | 10 | local type rockspec = require("luarocks.core.types.rockspec") |
11 | local type Rockspec = rockspec.Rockspec | ||
12 | 12 | ||
13 | --- Download sources for building a rock, using CVS. | 13 | --- Download sources for building a rock, using CVS. |
14 | -- @param rockspec table: The rockspec table | 14 | -- @param rockspec table: The rockspec table |
diff --git a/src/luarocks/fetch/git.tl b/src/luarocks/fetch/git.tl index f9eed558..1a4438c9 100644 --- a/src/luarocks/fetch/git.tl +++ b/src/luarocks/fetch/git.tl | |||
@@ -8,10 +8,11 @@ local fs = require("luarocks.fs") | |||
8 | local dir = require("luarocks.dir") | 8 | local dir = require("luarocks.dir") |
9 | local vers = require("luarocks.core.vers") | 9 | local vers = require("luarocks.core.vers") |
10 | local util = require("luarocks.util") | 10 | local util = require("luarocks.util") |
11 | local cfg = require("luarocks.core.cfg") --! | ||
12 | 11 | ||
13 | local type Rockspec = cfg.Rockspec | 12 | local type rockspec = require("luarocks.core.types.rockspec") |
14 | local type Version = vers.Version | 13 | local type Rockspec = rockspec.Rockspec |
14 | local type version = require("luarocks.core.types.version") | ||
15 | local type Version = version.Version | ||
15 | 16 | ||
16 | local cached_git_version: Version | 17 | local cached_git_version: Version |
17 | 18 | ||
diff --git a/src/luarocks/fetch/git_file.tl b/src/luarocks/fetch/git_file.tl index cd2f3405..858e67a3 100644 --- a/src/luarocks/fetch/git_file.tl +++ b/src/luarocks/fetch/git_file.tl | |||
@@ -4,9 +4,9 @@ local record git_file | |||
4 | end | 4 | end |
5 | 5 | ||
6 | local git = require("luarocks.fetch.git") | 6 | local git = require("luarocks.fetch.git") |
7 | local cfg = require("luarocks.core.cfg") --! | ||
8 | 7 | ||
9 | local type Rockspec = cfg.Rockspec | 8 | local type rockspec = require("luarocks.core.types.rockspec") |
9 | local type Rockspec = rockspec.Rockspec | ||
10 | 10 | ||
11 | --- Fetch sources for building a rock from a local Git repository. | 11 | --- Fetch sources for building a rock from a local Git repository. |
12 | -- @param rockspec table: The rockspec table | 12 | -- @param rockspec table: The rockspec table |
diff --git a/src/luarocks/fetch/git_http.tl b/src/luarocks/fetch/git_http.tl index b0164c1b..a7b3d692 100644 --- a/src/luarocks/fetch/git_http.tl +++ b/src/luarocks/fetch/git_http.tl | |||
@@ -11,9 +11,9 @@ local record git_http | |||
11 | end | 11 | end |
12 | 12 | ||
13 | local git = require("luarocks.fetch.git") | 13 | local git = require("luarocks.fetch.git") |
14 | local cfg = require("luarocks.core.cfg") --! | ||
15 | 14 | ||
16 | local type Rockspec = cfg.Rockspec | 15 | local type rockspec = require("luarocks.core.types.rockspec") |
16 | local type Rockspec = rockspec.Rockspec | ||
17 | 17 | ||
18 | --- Fetch sources for building a rock from a local Git repository. | 18 | --- Fetch sources for building a rock from a local Git repository. |
19 | -- @param rockspec table: The rockspec table | 19 | -- @param rockspec table: The rockspec table |
diff --git a/src/luarocks/fetch/git_ssh.tl b/src/luarocks/fetch/git_ssh.tl index 7cb68be3..65954353 100644 --- a/src/luarocks/fetch/git_ssh.tl +++ b/src/luarocks/fetch/git_ssh.tl | |||
@@ -11,9 +11,9 @@ local record git_ssh | |||
11 | end | 11 | end |
12 | 12 | ||
13 | local git = require("luarocks.fetch.git") | 13 | local git = require("luarocks.fetch.git") |
14 | local cfg = require("luarocks.core.cfg") --! | ||
15 | 14 | ||
16 | local type Rockspec = cfg.Rockspec | 15 | local type rockspec = require("luarocks.core.types.rockspec") |
16 | local type Rockspec = rockspec.Rockspec | ||
17 | 17 | ||
18 | --- Fetch sources for building a rock from a local Git repository. | 18 | --- Fetch sources for building a rock from a local Git repository. |
19 | -- @param rockspec table: The rockspec table | 19 | -- @param rockspec table: The rockspec table |
diff --git a/src/luarocks/fetch/hg.tl b/src/luarocks/fetch/hg.tl index 1acc2bea..0fbf5601 100644 --- a/src/luarocks/fetch/hg.tl +++ b/src/luarocks/fetch/hg.tl | |||
@@ -6,9 +6,9 @@ end | |||
6 | local fs = require("luarocks.fs") | 6 | local fs = require("luarocks.fs") |
7 | local dir = require("luarocks.dir") | 7 | local dir = require("luarocks.dir") |
8 | local util = require("luarocks.util") | 8 | local util = require("luarocks.util") |
9 | local cfg = require("luarocks.core.cfg") --! | ||
10 | 9 | ||
11 | local type Rockspec = cfg.Rockspec | 10 | local type rockspec = require("luarocks.core.types.rockspec") |
11 | local type Rockspec = rockspec.Rockspec | ||
12 | 12 | ||
13 | --- Download sources for building a rock, using hg. | 13 | --- Download sources for building a rock, using hg. |
14 | -- @param rockspec table: The rockspec table | 14 | -- @param rockspec table: The rockspec table |
diff --git a/src/luarocks/fetch/hg_http.tl b/src/luarocks/fetch/hg_http.tl index b51bc1e9..f526d2d5 100644 --- a/src/luarocks/fetch/hg_http.tl +++ b/src/luarocks/fetch/hg_http.tl | |||
@@ -9,9 +9,9 @@ local record hg_http | |||
9 | end | 9 | end |
10 | 10 | ||
11 | local hg = require("luarocks.fetch.hg") | 11 | local hg = require("luarocks.fetch.hg") |
12 | local cfg = require("luarocks.core.cfg") --! | ||
13 | 12 | ||
14 | local type Rockspec = cfg.Rockspec | 13 | local type rockspec = require("luarocks.core.types.rockspec") |
14 | local type Rockspec = rockspec.Rockspec | ||
15 | 15 | ||
16 | --- Download sources for building a rock, using hg over http. | 16 | --- Download sources for building a rock, using hg over http. |
17 | -- @param rockspec table: The rockspec table | 17 | -- @param rockspec table: The rockspec table |
diff --git a/src/luarocks/fetch/sscm.tl b/src/luarocks/fetch/sscm.tl index f708267c..ad5a615e 100644 --- a/src/luarocks/fetch/sscm.tl +++ b/src/luarocks/fetch/sscm.tl | |||
@@ -5,9 +5,9 @@ end | |||
5 | 5 | ||
6 | local fs = require("luarocks.fs") | 6 | local fs = require("luarocks.fs") |
7 | local dir = require("luarocks.dir") | 7 | local dir = require("luarocks.dir") |
8 | local cfg = require("luarocks.core.cfg") --! | ||
9 | 8 | ||
10 | local Rockspec = cfg.Rockspec | 9 | local type rockspec = require("luarocks.core.types.rockspec") |
10 | local type Rockspec = rockspec.Rockspec | ||
11 | 11 | ||
12 | --- Download sources via Surround SCM Server for building a rock. | 12 | --- Download sources via Surround SCM Server for building a rock. |
13 | -- @param rockspec table: The rockspec table | 13 | -- @param rockspec table: The rockspec table |
@@ -17,8 +17,6 @@ local Rockspec = cfg.Rockspec | |||
17 | -- the fetched source tarball and the temporary directory created to | 17 | -- the fetched source tarball and the temporary directory created to |
18 | -- store it; or nil and an error message. | 18 | -- store it; or nil and an error message. |
19 | function sscm.get_sources(rockspec: Rockspec, extract: boolean, dest_dir?: string): string, string | 19 | function sscm.get_sources(rockspec: Rockspec, extract: boolean, dest_dir?: string): string, string |
20 | assert(rockspec:type() == "rockspec") | ||
21 | assert(type(dest_dir) == "string" or not dest_dir) | ||
22 | 20 | ||
23 | local sscm_cmd = rockspec.variables.SSCM | 21 | local sscm_cmd = rockspec.variables.SSCM |
24 | local module = rockspec.source.module or dir.base_name(rockspec.source.url) | 22 | local module = rockspec.source.module or dir.base_name(rockspec.source.url) |
diff --git a/src/luarocks/fetch/svn.tl b/src/luarocks/fetch/svn.tl index 43355e63..df3cdde9 100644 --- a/src/luarocks/fetch/svn.tl +++ b/src/luarocks/fetch/svn.tl | |||
@@ -6,9 +6,9 @@ end | |||
6 | local fs = require("luarocks.fs") | 6 | local fs = require("luarocks.fs") |
7 | local dir = require("luarocks.dir") | 7 | local dir = require("luarocks.dir") |
8 | local util = require("luarocks.util") | 8 | local util = require("luarocks.util") |
9 | local cfg = require("luarocks.core.cfg") --! | ||
10 | 9 | ||
11 | local Rockspec = cfg.Rockspec | 10 | local type rockspec = require("luarocks.core.types.rockspec") |
11 | local type Rockspec = rockspec.Rockspec | ||
12 | 12 | ||
13 | --- Download sources for building a rock, using Subversion. | 13 | --- Download sources for building a rock, using Subversion. |
14 | -- @param rockspec table: The rockspec table | 14 | -- @param rockspec table: The rockspec table |
@@ -18,8 +18,6 @@ local Rockspec = cfg.Rockspec | |||
18 | -- the fetched source tarball and the temporary directory created to | 18 | -- the fetched source tarball and the temporary directory created to |
19 | -- store it; or nil and an error message. | 19 | -- store it; or nil and an error message. |
20 | function svn.get_sources(rockspec: Rockspec, extract: boolean, dest_dir?: string): string, string | 20 | function svn.get_sources(rockspec: Rockspec, extract: boolean, dest_dir?: string): string, string |
21 | assert(rockspec:type() == "rockspec") | ||
22 | assert(type(dest_dir) == "string" or not dest_dir) | ||
23 | 21 | ||
24 | local svn_cmd = rockspec.variables.SVN | 22 | local svn_cmd = rockspec.variables.SVN |
25 | local ok, err_msg = fs.is_tool_available(svn_cmd, "Subversion") | 23 | local ok, err_msg = fs.is_tool_available(svn_cmd, "Subversion") |
diff --git a/src/luarocks/loader.tl b/src/luarocks/loader.tl new file mode 100644 index 00000000..896b7ce1 --- /dev/null +++ b/src/luarocks/loader.tl | |||
@@ -0,0 +1,270 @@ | |||
1 | --- A module which installs a Lua package loader that is LuaRocks-aware. | ||
2 | -- This loader uses dependency information from the LuaRocks tree to load | ||
3 | -- correct versions of modules. It does this by constructing a "context" | ||
4 | -- table in the environment, which records which versions of packages were | ||
5 | -- used to load previous modules, so that the loader chooses versions | ||
6 | -- that are declared to be compatible with the ones loaded earlier. | ||
7 | |||
8 | -- luacheck: globals luarocks | ||
9 | |||
10 | local loaders = package.loaders or package.searchers | ||
11 | local require, ipairs, table, type, next, tostring, error = | ||
12 | require, ipairs, table, type, next, tostring, error | ||
13 | local unpack = unpack or table.unpack | ||
14 | |||
15 | local record loader | ||
16 | end | ||
17 | |||
18 | local is_clean = not package.loaded["luarocks.core.cfg"] | ||
19 | |||
20 | -- This loader module depends only on core modules. | ||
21 | local cfg = require("luarocks.core.cfg") | ||
22 | local cfg_ok, err = cfg.init() | ||
23 | if cfg_ok then | ||
24 | cfg.init_package_paths() | ||
25 | end | ||
26 | |||
27 | local path = require("luarocks.core.path") | ||
28 | local manif = require("luarocks.core.manif") | ||
29 | local vers = require("luarocks.core.vers") | ||
30 | local require = nil -- luacheck: ignore 411 | ||
31 | -------------------------------------------------------------------------------- | ||
32 | |||
33 | -- Workaround for wrappers produced by older versions of LuaRocks | ||
34 | local temporary_global = false | ||
35 | local status, luarocks_value = pcall(function() return luarocks end) | ||
36 | if status and luarocks_value then | ||
37 | -- The site_config.lua file generated by old versions uses module(), | ||
38 | -- so it produces a global `luarocks` table. Since we have the table, | ||
39 | -- add the `loader` field to make the old wrappers happy. | ||
40 | luarocks.loader = loader | ||
41 | else | ||
42 | -- When a new version is installed on top of an old version, | ||
43 | -- site_config.lua may be replaced, and then it no longer creates | ||
44 | -- a global. | ||
45 | -- Detect when being called via -lluarocks.loader; this is | ||
46 | -- most likely a wrapper. | ||
47 | local info = debug and debug.getinfo(2, "nS") | ||
48 | if info and info.what == "C" and not info.name then | ||
49 | luarocks = { loader = loader } | ||
50 | temporary_global = true | ||
51 | -- For the other half of this hack, | ||
52 | -- see the next use of `temporary_global` below. | ||
53 | end | ||
54 | end | ||
55 | |||
56 | loader.context = {} | ||
57 | |||
58 | --- Process the dependencies of a package to determine its dependency | ||
59 | -- chain for loading modules. | ||
60 | -- @param name string: The name of an installed rock. | ||
61 | -- @param version string: The version of the rock, in string format | ||
62 | function loader.add_context(name, version) | ||
63 | -- assert(type(name) == "string") | ||
64 | -- assert(type(version) == "string") | ||
65 | |||
66 | if temporary_global then | ||
67 | -- The first thing a wrapper does is to call add_context. | ||
68 | -- From here on, it's safe to clean the global environment. | ||
69 | luarocks = nil | ||
70 | temporary_global = false | ||
71 | end | ||
72 | |||
73 | local tree_manifests = manif.load_rocks_tree_manifests() | ||
74 | if not tree_manifests then | ||
75 | return nil | ||
76 | end | ||
77 | |||
78 | return manif.scan_dependencies(name, version, tree_manifests, loader.context) | ||
79 | end | ||
80 | |||
81 | --- Internal sorting function. | ||
82 | -- @param a table: A provider table. | ||
83 | -- @param b table: Another provider table. | ||
84 | -- @return boolean: True if the version of a is greater than that of b. | ||
85 | local function sort_versions(a,b) | ||
86 | return a.version > b.version | ||
87 | end | ||
88 | |||
89 | --- Request module to be loaded through other loaders, | ||
90 | -- once the proper name of the module has been determined. | ||
91 | -- For example, in case the module "socket.core" has been requested | ||
92 | -- to the LuaRocks loader and it determined based on context that | ||
93 | -- the version 2.0.2 needs to be loaded and it is not the current | ||
94 | -- version, the module requested for the other loaders will be | ||
95 | -- "socket.core_2_0_2". | ||
96 | -- @param module The module name requested by the user, such as "socket.core" | ||
97 | -- @param name The rock name, such as "luasocket" | ||
98 | -- @param version The rock version, such as "2.0.2-1" | ||
99 | -- @param module_name The actual module name, such as "socket.core" or "socket.core_2_0_2". | ||
100 | -- @return table or (nil, string): The module table as returned by some other loader, | ||
101 | -- or nil followed by an error message if no other loader managed to load the module. | ||
102 | local function call_other_loaders(module, name, version, module_name) | ||
103 | for _, a_loader in ipairs(loaders) do | ||
104 | if a_loader ~= loader.luarocks_loader then | ||
105 | local results = { a_loader(module_name) } | ||
106 | if type(results[1]) == "function" then | ||
107 | return unpack(results) | ||
108 | end | ||
109 | end | ||
110 | end | ||
111 | return "Failed loading module "..module.." in LuaRocks rock "..name.." "..version | ||
112 | end | ||
113 | |||
114 | local function add_providers(providers, entries, tree, module, filter_file_name) | ||
115 | for i, entry in ipairs(entries) do | ||
116 | local name, version = entry:match("^([^/]*)/(.*)$") | ||
117 | local file_name = tree.manifest.repository[name][version][1].modules[module] | ||
118 | if type(file_name) ~= "string" then | ||
119 | error("Invalid data in manifest file for module "..tostring(module).." (invalid data for "..tostring(name).." "..tostring(version)..")") | ||
120 | end | ||
121 | file_name = filter_file_name(file_name, name, version, tree.tree, i) | ||
122 | if loader.context[name] == version then | ||
123 | return name, version, file_name | ||
124 | end | ||
125 | version = vers.parse_version(version) | ||
126 | table.insert(providers, {name = name, version = version, module_name = file_name, tree = tree}) | ||
127 | end | ||
128 | end | ||
129 | |||
130 | --- Search for a module in the rocks trees | ||
131 | -- @param module string: module name (eg. "socket.core") | ||
132 | -- @param filter_file_name function(string, string, string, string, number): | ||
133 | -- a function that takes the module file name (eg "socket/core.so"), the rock name | ||
134 | -- (eg "luasocket"), the version (eg "2.0.2-1"), the path of the rocks tree | ||
135 | -- (eg "/usr/local"), and the numeric index of the matching entry, so the | ||
136 | -- filter function can know if the matching module was the first entry or not. | ||
137 | -- @return string, string, string, (string or table): | ||
138 | -- * name of the rock containing the module (eg. "luasocket") | ||
139 | -- * version of the rock (eg. "2.0.2-1") | ||
140 | -- * return value of filter_file_name | ||
141 | -- * tree of the module (string or table in `tree_manifests` format) | ||
142 | local function select_module(module, filter_file_name) | ||
143 | --assert(type(module) == "string") | ||
144 | --assert(type(filter_module_name) == "function") | ||
145 | |||
146 | local tree_manifests = manif.load_rocks_tree_manifests() | ||
147 | if not tree_manifests then | ||
148 | return nil | ||
149 | end | ||
150 | |||
151 | local providers = {} | ||
152 | local initmodule | ||
153 | for _, tree in ipairs(tree_manifests) do | ||
154 | local entries = tree.manifest.modules[module] | ||
155 | if entries then | ||
156 | local n, v, f = add_providers(providers, entries, tree, module, filter_file_name) | ||
157 | if n then | ||
158 | return n, v, f | ||
159 | end | ||
160 | else | ||
161 | initmodule = initmodule or module .. ".init" | ||
162 | entries = tree.manifest.modules[initmodule] | ||
163 | if entries then | ||
164 | local n, v, f = add_providers(providers, entries, tree, initmodule, filter_file_name) | ||
165 | if n then | ||
166 | return n, v, f | ||
167 | end | ||
168 | end | ||
169 | end | ||
170 | end | ||
171 | |||
172 | if next(providers) then | ||
173 | table.sort(providers, sort_versions) | ||
174 | local first = providers[1] | ||
175 | return first.name, first.version.string, first.module_name, first.tree | ||
176 | end | ||
177 | end | ||
178 | |||
179 | --- Search for a module | ||
180 | -- @param module string: module name (eg. "socket.core") | ||
181 | -- @return string, string, string, (string or table): | ||
182 | -- * name of the rock containing the module (eg. "luasocket") | ||
183 | -- * version of the rock (eg. "2.0.2-1") | ||
184 | -- * name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is stored versioned). | ||
185 | -- * tree of the module (string or table in `tree_manifests` format) | ||
186 | local function pick_module(module) | ||
187 | return | ||
188 | select_module(module, function(file_name, name, version, tree, i) | ||
189 | if i > 1 then | ||
190 | file_name = path.versioned_name(file_name, "", name, version) | ||
191 | end | ||
192 | return path.path_to_module(file_name) | ||
193 | end) | ||
194 | end | ||
195 | |||
196 | --- Return the pathname of the file that would be loaded for a module. | ||
197 | -- @param module string: module name (eg. "socket.core") | ||
198 | -- @param where string: places to look for the module. If `where` contains | ||
199 | -- "l", it will search using the LuaRocks loader; if it contains "p", | ||
200 | -- it will look in the filesystem using package.path and package.cpath. | ||
201 | -- You can use both at the same time. | ||
202 | -- @return If successful, it will return four values. | ||
203 | -- * If found using the LuaRocks loader, it will return: | ||
204 | -- * filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so"), | ||
205 | -- * rock name | ||
206 | -- * rock version | ||
207 | -- * "l" to indicate the match comes from the loader. | ||
208 | -- * If found scanning package.path and package.cpath, it will return: | ||
209 | -- * filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so"), | ||
210 | -- * "path" or "cpath" | ||
211 | -- * nil | ||
212 | -- * "p" to indicate the match comes from scanning package.path and cpath. | ||
213 | -- If unsuccessful, nothing is returned. | ||
214 | function loader.which(module, where) | ||
215 | where = where or "l" | ||
216 | if where:match("l") then | ||
217 | local rock_name, rock_version, file_name = select_module(module, path.which_i) | ||
218 | if rock_name then | ||
219 | local fd = io.open(file_name) | ||
220 | if fd then | ||
221 | fd:close() | ||
222 | return file_name, rock_name, rock_version, "l" | ||
223 | end | ||
224 | end | ||
225 | end | ||
226 | if where:match("p") then | ||
227 | local modpath = module:gsub("%.", "/") | ||
228 | for _, v in ipairs({"path", "cpath"}) do | ||
229 | for p in package[v]:gmatch("([^;]+)") do | ||
230 | local file_name = p:gsub("%?", modpath) -- luacheck: ignore 421 | ||
231 | local fd = io.open(file_name) | ||
232 | if fd then | ||
233 | fd:close() | ||
234 | return file_name, v, nil, "p" | ||
235 | end | ||
236 | end | ||
237 | end | ||
238 | end | ||
239 | end | ||
240 | |||
241 | --- Package loader for LuaRocks support. | ||
242 | -- A module is searched in installed rocks that match the | ||
243 | -- current LuaRocks context. If module is not part of the | ||
244 | -- context, or if a context has not yet been set, the module | ||
245 | -- in the package with the highest version is used. | ||
246 | -- @param module string: The module name, like in plain require(). | ||
247 | -- @return table: The module table (typically), like in plain | ||
248 | -- require(). See <a href="http://www.lua.org/manual/5.1/manual.html#pdf-require">require()</a> | ||
249 | -- in the Lua reference manual for details. | ||
250 | function loader.luarocks_loader(module) | ||
251 | local name, version, module_name = pick_module(module) | ||
252 | if not name then | ||
253 | return "No LuaRocks module found for "..module | ||
254 | else | ||
255 | loader.add_context(name, version) | ||
256 | return call_other_loaders(module, name, version, module_name) | ||
257 | end | ||
258 | end | ||
259 | |||
260 | table.insert(loaders, 1, loader.luarocks_loader) | ||
261 | |||
262 | if is_clean then | ||
263 | for modname, _ in pairs(package.loaded) do | ||
264 | if modname:match("^luarocks%.") then | ||
265 | package.loaded[modname] = nil | ||
266 | end | ||
267 | end | ||
268 | end | ||
269 | |||
270 | return loader | ||
diff --git a/src/luarocks/manif.tl b/src/luarocks/manif.tl index a7949932..f0f838b8 100644 --- a/src/luarocks/manif.tl +++ b/src/luarocks/manif.tl | |||
@@ -19,9 +19,11 @@ local util = require("luarocks.util") | |||
19 | local queries = require("luarocks.queries") | 19 | local queries = require("luarocks.queries") |
20 | local type_manifest = require("luarocks.type.manifest") | 20 | local type_manifest = require("luarocks.type.manifest") |
21 | 21 | ||
22 | local type tree = require("luarocks.core.types.tree") | ||
23 | local type Tree = tree.Tree | ||
22 | local type Manifest = core.Manifest | 24 | local type Manifest = core.Manifest |
23 | local type Tree_manifest = core.Tree_manifest | 25 | local type Tree_manifest = core.Tree_manifest |
24 | local type Tree = cfg.Tree | 26 | local type DependencyVersion = core.DependencyVersion --! |
25 | 27 | ||
26 | manif.cache_manifest = core.cache_manifest | 28 | manif.cache_manifest = core.cache_manifest |
27 | manif.load_rocks_tree_manifests = core.load_rocks_tree_manifests | 29 | manif.load_rocks_tree_manifests = core.load_rocks_tree_manifests |
@@ -190,14 +192,13 @@ end | |||
190 | -- or "all", to use all trees. | 192 | -- or "all", to use all trees. |
191 | -- @return table: An array of strings listing installed | 193 | -- @return table: An array of strings listing installed |
192 | -- versions of a package, and a table indicating where they are found. | 194 | -- versions of a package, and a table indicating where they are found. |
193 | function manif.get_versions(dep, deps_mode: string): {string}, {string: string | Tree} | 195 | function manif.get_versions(dep: DependencyVersion, deps_mode: string): {string}, {string: string | Tree} |
194 | -- assert(type(dep) == "table") --! | ||
195 | 196 | ||
196 | local name: string = dep.name | 197 | local name: string = dep.name |
197 | local namespace: string = dep.namespace | 198 | local namespace: string = dep.namespace |
198 | 199 | ||
199 | local version_set = {} | 200 | local version_set = {} |
200 | path.map_trees(deps_mode, function(tree) | 201 | path.map_trees(deps_mode, function(tree: string | Tree) |
201 | local manifest = manif.load_manifest(path.rocks_dir(tree)) | 202 | local manifest = manif.load_manifest(path.rocks_dir(tree)) |
202 | 203 | ||
203 | if manifest and manifest.repository[name] then | 204 | if manifest and manifest.repository[name] then |
diff --git a/src/luarocks/path.tl b/src/luarocks/path.tl index f350f80c..1dc77e86 100644 --- a/src/luarocks/path.tl +++ b/src/luarocks/path.tl | |||
@@ -8,7 +8,8 @@ local core = require("luarocks.core.path") | |||
8 | local dir = require("luarocks.dir") | 8 | local dir = require("luarocks.dir") |
9 | local util = require("luarocks.core.util") | 9 | local util = require("luarocks.core.util") |
10 | 10 | ||
11 | local type Tree = cfg.Tree | 11 | local type tree = require("luarocks.core.types.tree") |
12 | local type Tree = tree.Tree | ||
12 | 13 | ||
13 | local record path | 14 | local record path |
14 | rocks_dir: function(string | Tree): string | 15 | rocks_dir: function(string | Tree): string |
diff --git a/src/luarocks/queries.tl b/src/luarocks/queries.tl index 749cafe9..dec57585 100644 --- a/src/luarocks/queries.tl +++ b/src/luarocks/queries.tl | |||
@@ -1,31 +1,27 @@ | |||
1 | 1 | ||
2 | local record queries | 2 | local record queries |
3 | record Query | ||
4 | name: string | ||
5 | namespace: string | ||
6 | constraints: {vers.Constraint} | ||
7 | substring: boolean | ||
8 | arch: {string: boolean} | ||
9 | end | ||
10 | end | 3 | end |
11 | 4 | ||
12 | local vers = require("luarocks.core.vers") | 5 | local vers = require("luarocks.core.vers") |
13 | local util = require("luarocks.util") | 6 | local util = require("luarocks.util") |
14 | local cfg = require("luarocks.core.cfg") | 7 | local cfg = require("luarocks.core.cfg") |
15 | 8 | ||
16 | local type Query = queries.Query | 9 | local type query = require("luarocks.core.types.query") |
17 | local type Constraint = vers.Constraint | 10 | local type version = require("luarocks.core.types.version") |
11 | local type Query = query.Query | ||
12 | local type Version = version.Version | ||
13 | local type Constraint = version.Constraint | ||
18 | 14 | ||
19 | local query_mt: metatable<Query> = {} | 15 | local query_mt: metatable<Query> = {} |
20 | 16 | ||
21 | query_mt.__index = queries.Query | 17 | query_mt.__index = query.Query |
22 | 18 | ||
23 | function queries.Query.type(): string --? remove later | 19 | function query.Query.type(): string --? remove later |
24 | return "query" | 20 | return "query" |
25 | end | 21 | end |
26 | 22 | ||
27 | -- Fallback default value for the `arch` field, if not explicitly set. | 23 | -- Fallback default value for the `arch` field, if not explicitly set. |
28 | queries.Query.arch = { | 24 | query.Query.arch = { |
29 | src = true, | 25 | src = true, |
30 | all = true, | 26 | all = true, |
31 | rockspec = true, | 27 | rockspec = true, |
@@ -34,7 +30,7 @@ queries.Query.arch = { | |||
34 | } | 30 | } |
35 | 31 | ||
36 | -- Fallback default value for the `substring` field, if not explicitly set. | 32 | -- Fallback default value for the `substring` field, if not explicitly set. |
37 | queries.Query.substring = false | 33 | query.Query.substring = false |
38 | 34 | ||
39 | --- Convert the arch field of a query table to table format. | 35 | --- Convert the arch field of a query table to table format. |
40 | -- @param input string, table or nil | 36 | -- @param input string, table or nil |
@@ -79,7 +75,7 @@ function queries.new(name: string, namespace?: string, version?: string, substri | |||
79 | table.insert(self.constraints, { op = operator, version = vers.parse_version(version)}) | 75 | table.insert(self.constraints, { op = operator, version = vers.parse_version(version)}) |
80 | end | 76 | end |
81 | 77 | ||
82 | queries.Query.arch[cfg.arch] = true | 78 | query.Query.arch[cfg.arch] = true |
83 | return setmetatable(self, query_mt) | 79 | return setmetatable(self, query_mt) |
84 | end | 80 | end |
85 | 81 | ||
@@ -183,13 +179,13 @@ do | |||
183 | constraints = constraints, | 179 | constraints = constraints, |
184 | } | 180 | } |
185 | 181 | ||
186 | queries.Query.arch[cfg.arch] = true | 182 | query.Query.arch[cfg.arch] = true |
187 | return setmetatable(self, query_mt) | 183 | return setmetatable(self, query_mt) |
188 | end | 184 | end |
189 | end | 185 | end |
190 | 186 | ||
191 | function queries.from_persisted_table(tbl: Query): Query | 187 | function queries.from_persisted_table(tbl: Query): Query |
192 | queries.Query.arch[cfg.arch] = true | 188 | query.Query.arch[cfg.arch] = true |
193 | return setmetatable(tbl, query_mt) | 189 | return setmetatable(tbl, query_mt) |
194 | end | 190 | end |
195 | 191 | ||
@@ -209,9 +205,9 @@ function query_mt.__tostring(self: Query): string | |||
209 | local pretty = {} | 205 | local pretty = {} |
210 | for _, c in ipairs(self.constraints) do | 206 | for _, c in ipairs(self.constraints) do |
211 | local cv = c.version | 207 | local cv = c.version |
212 | -- local v = cv is vers.Version and cv.string or cv --TEAL BUG | 208 | -- local v = cv is Version and cv.string or cv --TEAL BUG |
213 | local v: string | 209 | local v: string |
214 | if cv is vers.Version then | 210 | if cv is Version then |
215 | v = cv.string | 211 | v = cv.string |
216 | else | 212 | else |
217 | v = cv | 213 | v = cv |
diff --git a/src/luarocks/results.tl b/src/luarocks/results.tl index cae6ead9..99f70ec4 100644 --- a/src/luarocks/results.tl +++ b/src/luarocks/results.tl | |||
@@ -10,10 +10,10 @@ end | |||
10 | 10 | ||
11 | local vers = require("luarocks.core.vers") | 11 | local vers = require("luarocks.core.vers") |
12 | local util = require("luarocks.util") | 12 | local util = require("luarocks.util") |
13 | local queries = require("luarocks.queries") | 13 | local type query = require("luarocks.core.types.query") |
14 | 14 | ||
15 | local type Results = results.Results | 15 | local type Results = results.Results |
16 | local type Query = queries.Query | 16 | local type Query = query.Query |
17 | 17 | ||
18 | local result_mt: metatable<Results> = {} | 18 | local result_mt: metatable<Results> = {} |
19 | 19 | ||
diff --git a/src/luarocks/rockspecs.tl b/src/luarocks/rockspecs.tl index 390b4d5d..cdd0dcff 100644 --- a/src/luarocks/rockspecs.tl +++ b/src/luarocks/rockspecs.tl | |||
@@ -9,9 +9,9 @@ local type_rockspec = require("luarocks.type.rockspec") | |||
9 | local util = require("luarocks.util") | 9 | local util = require("luarocks.util") |
10 | local vers = require("luarocks.core.vers") | 10 | local vers = require("luarocks.core.vers") |
11 | 11 | ||
12 | local type Rockspec = cfg.Rockspec | 12 | local type rockspec = require("luarocks.core.types.rockspec") |
13 | local type Variables = cfg.Variables | 13 | local type Rockspec = rockspec.Rockspec |
14 | local type Dependencie = cfg.Dependencie | 14 | local type Variables = rockspec.Variables |
15 | 15 | ||
16 | local vendored_build_type_set: {string: boolean} = { | 16 | local vendored_build_type_set: {string: boolean} = { |
17 | ["builtin"] = true, | 17 | ["builtin"] = true, |
@@ -24,9 +24,9 @@ local vendored_build_type_set: {string: boolean} = { | |||
24 | 24 | ||
25 | local rockspec_mt: metatable<Rockspec> = {} | 25 | local rockspec_mt: metatable<Rockspec> = {} |
26 | 26 | ||
27 | rockspec_mt.__index = cfg.Rockspec | 27 | rockspec_mt.__index = rockspec.Rockspec |
28 | 28 | ||
29 | function cfg.Rockspec:type(): string | 29 | function rockspec.Rockspec.type(): string |
30 | return "rockspec" | 30 | return "rockspec" |
31 | end | 31 | end |
32 | 32 | ||
@@ -103,7 +103,7 @@ function rockspecs.from_persisted_table(filename: string, rockspec: Rockspec, gl | |||
103 | end | 103 | end |
104 | 104 | ||
105 | if not quick then | 105 | if not quick then |
106 | local ok, err = type_rockspec.check(rockspec as {any: any}, globals or {}) | 106 | local ok, err = type_rockspec.check(rockspec, globals or {}) |
107 | if not ok then | 107 | if not ok then |
108 | return nil, err | 108 | return nil, err |
109 | end | 109 | end |
diff --git a/src/luarocks/test.tl b/src/luarocks/test.tl new file mode 100644 index 00000000..58b055dd --- /dev/null +++ b/src/luarocks/test.tl | |||
@@ -0,0 +1,100 @@ | |||
1 | local record test | ||
2 | end | ||
3 | |||
4 | local fetch = require("luarocks.fetch") | ||
5 | local deps = require("luarocks.deps") | ||
6 | local util = require("luarocks.util") | ||
7 | |||
8 | local test_types = { | ||
9 | "busted", | ||
10 | "command", | ||
11 | } | ||
12 | |||
13 | local test_modules = {} | ||
14 | |||
15 | for _, test_type in ipairs(test_types) do | ||
16 | local mod = require("luarocks.test." .. test_type) | ||
17 | table.insert(test_modules, mod) | ||
18 | test_modules[test_type] = mod | ||
19 | test_modules[mod] = test_type | ||
20 | end | ||
21 | |||
22 | local function get_test_type(rockspec) | ||
23 | if rockspec.test and rockspec.test.type then | ||
24 | return rockspec.test.type | ||
25 | end | ||
26 | |||
27 | for _, test_module in ipairs(test_modules) do | ||
28 | if test_module.detect_type() then | ||
29 | return test_modules[test_module] | ||
30 | end | ||
31 | end | ||
32 | |||
33 | return nil, "could not detect test type -- no test suite for " .. rockspec.package .. "?" | ||
34 | end | ||
35 | |||
36 | -- Run test suite as configured in rockspec in the current directory. | ||
37 | function test.run_test_suite(rockspec_arg, test_type, args, prepare) | ||
38 | local rockspec | ||
39 | if type(rockspec_arg) == "string" then | ||
40 | local err, errcode | ||
41 | rockspec, err, errcode = fetch.load_rockspec(rockspec_arg) | ||
42 | if err then | ||
43 | return nil, err, errcode | ||
44 | end | ||
45 | else | ||
46 | assert(type(rockspec_arg) == "table") | ||
47 | rockspec = rockspec_arg | ||
48 | end | ||
49 | |||
50 | if not test_type then | ||
51 | local err | ||
52 | test_type, err = get_test_type(rockspec, test_type) | ||
53 | if not test_type then | ||
54 | return nil, err | ||
55 | end | ||
56 | end | ||
57 | assert(test_type) | ||
58 | |||
59 | local all_deps = { | ||
60 | "dependencies", | ||
61 | "build_dependencies", | ||
62 | "test_dependencies", | ||
63 | } | ||
64 | for _, dep_kind in ipairs(all_deps) do | ||
65 | if rockspec[dep_kind] and next(rockspec[dep_kind]) then | ||
66 | local ok, err, errcode = deps.fulfill_dependencies(rockspec, dep_kind, "all") | ||
67 | if err then | ||
68 | return nil, err, errcode | ||
69 | end | ||
70 | end | ||
71 | end | ||
72 | |||
73 | local mod_name = "luarocks.test." .. test_type | ||
74 | local pok, test_mod = pcall(require, mod_name) | ||
75 | if not pok then | ||
76 | return nil, "failed loading test execution module " .. mod_name | ||
77 | end | ||
78 | |||
79 | if prepare then | ||
80 | if test_type == "busted" then | ||
81 | return test_mod.run_tests(rockspec_arg, {"--version"}) | ||
82 | else | ||
83 | return true | ||
84 | end | ||
85 | else | ||
86 | local flags = rockspec.test and rockspec.test.flags | ||
87 | if type(flags) == "table" then | ||
88 | util.variable_substitutions(flags, rockspec.variables) | ||
89 | |||
90 | -- insert any flags given in test.flags at the front of args | ||
91 | for i = 1, #flags do | ||
92 | table.insert(args, i, flags[i]) | ||
93 | end | ||
94 | end | ||
95 | |||
96 | return test_mod.run_tests(rockspec.test, args) | ||
97 | end | ||
98 | end | ||
99 | |||
100 | return test | ||
diff --git a/src/luarocks/type/manifest.tl b/src/luarocks/type/manifest.tl index 0eca2f56..f379f1e0 100644 --- a/src/luarocks/type/manifest.tl +++ b/src/luarocks/type/manifest.tl | |||
@@ -80,7 +80,7 @@ local manifest_formats = type_check.declare_schemas({ | |||
80 | -- mismatches. | 80 | -- mismatches. |
81 | -- @return boolean or (nil, string): true if type checking | 81 | -- @return boolean or (nil, string): true if type checking |
82 | -- succeeded, or nil and an error message if it failed. | 82 | -- succeeded, or nil and an error message if it failed. |
83 | function type_manifest.check(manifest: {any: any}, globals: {string: any}): boolean, string | 83 | function type_manifest.check(manifest: {any: any}, globals: {string: any}): boolean, string --! |
84 | local format = manifest_formats["3.0"] | 84 | local format = manifest_formats["3.0"] |
85 | local ok, err = type_check.check_undeclared_globals(globals, format) | 85 | local ok, err = type_check.check_undeclared_globals(globals, format) |
86 | if not ok then return nil, err end | 86 | if not ok then return nil, err end |
diff --git a/src/luarocks/type/rockspec.tl b/src/luarocks/type/rockspec.tl index 6f431bd9..1b03736d 100644 --- a/src/luarocks/type/rockspec.tl +++ b/src/luarocks/type/rockspec.tl | |||
@@ -1,8 +1,11 @@ | |||
1 | local record type_rockspec | 1 | local record type_rockspec |
2 | order: util.Ordering<string> | 2 | order: Ordering<string> |
3 | rockspec_format: string | 3 | rockspec_format: string |
4 | end | 4 | end |
5 | 5 | ||
6 | local type ordering = require("luarocks.core.types.ordering") | ||
7 | local type Ordering = ordering.Ordering | ||
8 | |||
6 | local type_check = require("luarocks.type_check") | 9 | local type_check = require("luarocks.type_check") |
7 | local util = require("luarocks.core.util") --! | 10 | local util = require("luarocks.core.util") --! |
8 | 11 | ||
diff --git a/src/luarocks/util.tl b/src/luarocks/util.tl index 80742419..d39c2198 100644 --- a/src/luarocks/util.tl +++ b/src/luarocks/util.tl | |||
@@ -49,7 +49,8 @@ util.keys = core.keys | |||
49 | util.matchquote = core.matchquote | 49 | util.matchquote = core.matchquote |
50 | 50 | ||
51 | local type Fn = util.Fn | 51 | local type Fn = util.Fn |
52 | local type Rockspec = cfg.Rockspec | 52 | local type rockspec = require("luarocks.core.types.rockspec") |
53 | local type Rockspec = rockspec.Rockspec | ||
53 | local type Parser = util.Parser | 54 | local type Parser = util.Parser |
54 | 55 | ||
55 | 56 | ||