diff options
Diffstat (limited to 'src/luarocks/remove.tl')
-rw-r--r-- | src/luarocks/remove.tl | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/src/luarocks/remove.tl b/src/luarocks/remove.tl new file mode 100644 index 00000000..11d270a9 --- /dev/null +++ b/src/luarocks/remove.tl | |||
@@ -0,0 +1,140 @@ | |||
1 | |||
2 | local record remove | ||
3 | end | ||
4 | |||
5 | local search = require("luarocks.search") | ||
6 | local deps = require("luarocks.deps") | ||
7 | local fetch = require("luarocks.fetch") | ||
8 | local repos = require("luarocks.repos") | ||
9 | local repo_writer = require("luarocks.repo_writer") | ||
10 | local path = require("luarocks.path") | ||
11 | local util = require("luarocks.util") | ||
12 | local cfg = require("luarocks.core.cfg") | ||
13 | local manif = require("luarocks.manif") | ||
14 | local queries = require("luarocks.queries") | ||
15 | |||
16 | local type Result = require("luarocks.core.types.result").Result | ||
17 | |||
18 | --- Obtain a list of packages that depend on the given set of packages | ||
19 | -- (where all packages of the set are versions of one program). | ||
20 | -- @param name string: the name of a program | ||
21 | -- @param versions array of string: the versions to be deleted. | ||
22 | -- @return array of string: an empty table if no packages depend on any | ||
23 | -- of the given list, or an array of strings in "name/version" format. | ||
24 | local function check_dependents(name: string, versions: {string: {Result}}, deps_mode: string): {Result} | ||
25 | local dependents: {Result} = {} | ||
26 | |||
27 | local skip_set = {} | ||
28 | skip_set[name] = {} | ||
29 | for version, _ in pairs(versions) do | ||
30 | skip_set[name][version] = true | ||
31 | end | ||
32 | |||
33 | local local_rocks = {} | ||
34 | local query_all = queries.all() | ||
35 | search.local_manifest_search(local_rocks, cfg.rocks_dir, query_all) | ||
36 | local_rocks[name] = nil | ||
37 | for rock_name, rock_versions in pairs(local_rocks) do | ||
38 | for rock_version, _ in pairs(rock_versions) do | ||
39 | local rockspec, err = fetch.load_rockspec(path.rockspec_file(rock_name, rock_version)) | ||
40 | if rockspec then | ||
41 | local _, missing = deps.match_deps(rockspec.dependencies.queries, rockspec.rocks_provided, deps_mode, skip_set) | ||
42 | if missing[name] then | ||
43 | table.insert(dependents, { name = rock_name, version = rock_version }) | ||
44 | end | ||
45 | end | ||
46 | end | ||
47 | end | ||
48 | |||
49 | return dependents | ||
50 | end | ||
51 | |||
52 | --- Delete given versions of a program. | ||
53 | -- @param name string: the name of a program | ||
54 | -- @param versions array of string: the versions to be deleted. | ||
55 | -- @param deps_mode: string: Which trees to check dependencies for: | ||
56 | -- "one" for the current default tree, "all" for all trees, | ||
57 | -- "order" for all trees with priority >= the current default, "none" for no trees. | ||
58 | -- @return boolean or (nil, string): true on success or nil and an error message. | ||
59 | local function delete_versions(name: string, versions: {string: any}, deps_mode: string): boolean, string | ||
60 | |||
61 | for version, _ in pairs(versions) do | ||
62 | util.printout("Removing "..name.." "..version.."...") | ||
63 | local ok, err = repo_writer.delete_version(name, version, deps_mode) | ||
64 | if not ok then return nil, err end | ||
65 | end | ||
66 | |||
67 | return true | ||
68 | end | ||
69 | |||
70 | function remove.remove_search_results(results: {string : {string : {Result}}}, name: string, deps_mode: string, force: boolean, fast: boolean): boolean, string | ||
71 | local versions = results[name] | ||
72 | |||
73 | local version = next(versions) | ||
74 | local second = next(versions, version) | ||
75 | |||
76 | local dependents = {} | ||
77 | if not fast then | ||
78 | util.printout("Checking stability of dependencies in the absence of") | ||
79 | util.printout(name.." "..table.concat((util.keys(versions) as {string | number}), ", ").."...") | ||
80 | util.printout() | ||
81 | dependents = check_dependents(name, versions, deps_mode) | ||
82 | end | ||
83 | |||
84 | if #dependents > 0 then | ||
85 | if force or fast then | ||
86 | util.printerr("The following packages may be broken by this forced removal:") | ||
87 | for _, dependent in ipairs(dependents) do | ||
88 | util.printerr(dependent.name.." "..dependent.version) | ||
89 | end | ||
90 | util.printerr() | ||
91 | else | ||
92 | if not second then | ||
93 | util.printerr("Will not remove "..name.." "..version..".") | ||
94 | util.printerr("Removing it would break dependencies for: ") | ||
95 | else | ||
96 | util.printerr("Will not remove installed versions of "..name..".") | ||
97 | util.printerr("Removing them would break dependencies for: ") | ||
98 | end | ||
99 | for _, dependent in ipairs(dependents) do | ||
100 | util.printerr(dependent.name.." "..dependent.version) | ||
101 | end | ||
102 | util.printerr() | ||
103 | util.printerr("Use --force to force removal (warning: this may break modules).") | ||
104 | return nil, "Failed removing." | ||
105 | end | ||
106 | end | ||
107 | |||
108 | local ok, err = delete_versions(name, versions, deps_mode) | ||
109 | if not ok then return nil, err end | ||
110 | |||
111 | util.printout("Removal successful.") | ||
112 | return true | ||
113 | end | ||
114 | |||
115 | function remove.remove_other_versions(name: string, version: string, force: boolean, fast: boolean): boolean, string, string | ||
116 | local results = {} | ||
117 | local query = queries.new(name, nil, version, false, nil, "~=") | ||
118 | search.local_manifest_search(results, cfg.rocks_dir, query) | ||
119 | local warn: string | ||
120 | if results[name] then | ||
121 | local ok, err = remove.remove_search_results(results, name, cfg.deps_mode, force, fast) | ||
122 | if not ok then -- downgrade failure to a warning | ||
123 | warn = err | ||
124 | end | ||
125 | end | ||
126 | |||
127 | if not fast then | ||
128 | -- since we're not using --keep, this means that all files of the rock being installed | ||
129 | -- should be available as non-versioned variants. Double-check that: | ||
130 | local rock_manifest, load_err = manif.load_rock_manifest(name, version) | ||
131 | local ok, err = repos.check_everything_is_installed(name, version, rock_manifest, cfg.root_dir, false) | ||
132 | if not ok then | ||
133 | return nil, err | ||
134 | end | ||
135 | end | ||
136 | |||
137 | return true, nil, warn | ||
138 | end | ||
139 | |||
140 | return remove | ||