summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2021-05-27 20:58:00 +0800
committerGitHub <[email protected]>2021-05-27 20:58:00 +0800
commita7d455ce054ae7916cd75e9820e2b12db9b8dd12 (patch)
tree10eea582f96c0c827c05d0ace1273c7ac5749e81
parentcabfdf44c5b08ad2dfeb425eb5e372cbff6c37fe (diff)
parent57538bd32331d415730e0a82715d25f887bbc84a (diff)
Merge pull request #1429 from xmake-io/select
Ask xmake to try to install dependencies from 3rd package manager
-rw-r--r--xmake/core/base/utils.lua30
-rw-r--r--xmake/modules/private/action/require/impl/install_packages.lua222
2 files changed, 199 insertions, 53 deletions
diff --git a/xmake/core/base/utils.lua b/xmake/core/base/utils.lua
index 4071490f5..c1b78af4d 100644
--- a/xmake/core/base/utils.lua
+++ b/xmake/core/base/utils.lua
@@ -314,18 +314,18 @@ function utils.confirm(opt)
local description = opt.description or ""
-- get confirm result
- local confirm = option.get("yes") or option.get("confirm")
- if type(confirm) == "string" then
- confirm = confirm:lower()
- if confirm == "d" or confirm == "def" then
- confirm = default
+ local result = option.get("yes") or option.get("confirm")
+ if type(result) == "string" then
+ result = result:lower()
+ if result == "d" or result == "def" then
+ result = default
else
- confirm = nil
+ result = nil
end
end
-- get user confirm
- if confirm == nil then
+ if result == nil then
-- show tips
if type(description) == "function" then
@@ -333,16 +333,20 @@ function utils.confirm(opt)
else
utils.cprint("${bright color.warning}note: ${clear}%s (pass -y or --confirm=y/n/d to skip confirm)?", description)
end
- utils.cprint("please input: ${bright}%s${clear} (y/n)", default and "y" or "n")
-- get answer
- io.flush()
- confirm = option.boolean((io.read() or "false"):trim())
- if type(confirm) ~= "boolean" then
- confirm = default
+ if opt.answer then
+ result = opt.answer()
+ else
+ utils.cprint("please input: ${bright}%s${clear} (y/n)", default and "y" or "n")
+ io.flush()
+ result = option.boolean((io.read() or "false"):trim())
+ if type(result) ~= "boolean" then
+ result = default
+ end
end
end
- return confirm
+ return result
end
function utils.table(data, opt)
diff --git a/xmake/modules/private/action/require/impl/install_packages.lua b/xmake/modules/private/action/require/impl/install_packages.lua
index e2d97e2f3..97d0d18ba 100644
--- a/xmake/modules/private/action/require/impl/install_packages.lua
+++ b/xmake/modules/private/action/require/impl/install_packages.lua
@@ -46,6 +46,118 @@ function _sort_packages_urls(packages)
end
end
+-- replace modified package
+function _replace_package(packages, instance, extinstance)
+ for idx, rawinstance in ipairs(packages) do
+ if rawinstance == instance then
+ packages[idx] = extinstance
+ end
+ local deps = rawinstance._DEPS
+ for name, dep in pairs(deps) do
+ if dep == instance then
+ deps[name] = nil
+ deps[extinstance:name()] = extinstance
+ break
+ end
+ end
+ local parents = rawinstance._PARENTS
+ for name, parent in pairs(parents) do
+ if parent == instance then
+ parents[name] = nil
+ parents[extinstance:name()] = extinstance
+ break
+ end
+ end
+ local orderdeps = rawinstance._ORDERDEPS
+ for depidx, dep in ipairs(orderdeps) do
+ if dep == instance then
+ orderdeps[depidx] = extinstance
+ break
+ end
+ end
+ local linkdeps = rawinstance._LINKDEPS
+ for depidx, dep in ipairs(linkdeps) do
+ if dep == instance then
+ linkdeps[depidx] = extinstance
+ break
+ end
+ end
+ local plaindeps = rawinstance._PLAINDEPS
+ for depidx, dep in ipairs(rawinstance._PLAINDEPS) do
+ if dep == instance then
+ plaindeps[depidx] = extinstance
+ break
+ end
+ end
+ end
+end
+
+-- replace modified packages
+function _replace_packages(packages, packages_modified)
+ for _, package_modified in ipairs(packages_modified) do
+ local instance = package_modified.instance
+ local extinstance = package_modified.extinstance
+ _replace_package(packages, instance, extinstance)
+ end
+end
+
+-- get user confirm from 3rd package sources
+-- @see https://github.com/xmake-io/xmake/issues/1140
+function _get_confirm_from_3rd(packages)
+
+ -- get extpackages list
+ local extpackages_list = _g.extpackages_list
+ if not extpackages_list then
+ extpackages_list = {}
+ for _, instance in ipairs(packages) do
+ local extsources = instance:get("extsources")
+ local extsources_extra = instance:extraconf("extsources")
+ if extsources then
+ local extpackages = package.load_packages(extsources, extsources_extra)
+ for _, extinstance in ipairs(extpackages) do
+ table.insert(extpackages_list, {instance = instance, extinstance = extinstance})
+ end
+ end
+ end
+ _g.extpackages_list = extpackages_list
+ end
+
+ -- get confirm result
+ local result = utils.confirm({description = function ()
+ cprint("${bright color.warning}note: ${clear}select the following 3rd packages")
+ for idx, extinstance in ipairs(extpackages_list) do
+ local instance = extinstance.instance
+ local extinstance = extinstance.extinstance
+ cprint(" ${yellow}%d.${clear} %s ${yellow}->${clear} %s %s ${dim}%s",
+ idx, extinstance:name(),
+ instance:displayname(),
+ instance:version_str() or "",
+ package.get_configs_str(instance))
+ end
+ end, answer = function ()
+ cprint("please input number list: ${bright}n${clear} (1,2,..)")
+ io.flush()
+ return (io.read() or "n"):trim()
+ end})
+
+ -- get confirmed extpackages
+ local confirmed_extpackages = {}
+ if result and result ~= "n" then
+ for _, idx in ipairs(result:split(',')) do
+ idx = tonumber(idx)
+ if extpackages_list[idx] then
+ table.insert(confirmed_extpackages, extpackages_list[idx])
+ end
+ end
+ end
+
+ -- modify packages
+ if #confirmed_extpackages > 0 then
+ _replace_packages(packages, confirmed_extpackages)
+ return confirmed_extpackages
+ end
+end
+
-- get user confirm
function _get_confirm(packages)
@@ -54,54 +166,74 @@ function _get_confirm(packages)
return true
end
- -- get confirm
- local confirm = utils.confirm({default = true, description = function ()
+ local result
+ local packages_modified
+ while result == nil do
+ -- get confirm result
+ result = utils.confirm({default = true, description = function ()
- -- get packages for each repositories
- local packages_repo = {}
- local packages_group = {}
- for _, instance in ipairs(packages) do
- -- achive packages by repository
- local reponame = instance:repo() and instance:repo():name() or (instance:is_system() and "system" or "")
- if instance:is_thirdparty() then
- reponame = instance:name():lower():split("::")[1]
- end
- packages_repo[reponame] = packages_repo[reponame] or {}
- table.insert(packages_repo[reponame], instance)
+ -- get packages for each repositories
+ local packages_repo = {}
+ local packages_group = {}
+ for _, instance in ipairs(packages) do
+ -- achive packages by repository
+ local reponame = instance:repo() and instance:repo():name() or (instance:is_system() and "system" or "")
+ if instance:is_thirdparty() then
+ reponame = instance:name():lower():split("::")[1]
+ end
+ packages_repo[reponame] = packages_repo[reponame] or {}
+ table.insert(packages_repo[reponame], instance)
- -- achive packages by group
- local group = instance:group()
- if group then
- packages_group[group] = packages_group[group] or {}
- table.insert(packages_group[group], instance)
+ -- achive packages by group
+ local group = instance:group()
+ if group then
+ packages_group[group] = packages_group[group] or {}
+ table.insert(packages_group[group], instance)
+ end
end
- end
- -- show tips
- cprint("${bright color.warning}note: ${clear}try installing these packages (pass -y to skip confirm)?")
- for reponame, packages in pairs(packages_repo) do
- if reponame ~= "" then
- print("in %s:", reponame)
- end
- local packages_showed = {}
- for _, instance in ipairs(packages) do
- if not packages_showed[tostring(instance)] then
- local group = instance:group()
- if group and packages_group[group] and #packages_group[group] > 1 then
- for idx, package_in_group in ipairs(packages_group[group]) do
- cprint(" ${yellow}%s${clear} %s %s ${dim}%s", idx == 1 and "->" or " or", package_in_group:displayname(), package_in_group:version_str() or "", package.get_configs_str(package_in_group))
- packages_showed[tostring(package_in_group)] = true
+ -- show tips
+ cprint("${bright color.warning}note: ${clear}install or modify (m) these packages (pass -y to skip confirm)?")
+ for reponame, packages in pairs(packages_repo) do
+ if reponame ~= "" then
+ print("in %s:", reponame)
+ end
+ local packages_showed = {}
+ for _, instance in ipairs(packages) do
+ if not packages_showed[tostring(instance)] then
+ local group = instance:group()
+ if group and packages_group[group] and #packages_group[group] > 1 then
+ for idx, package_in_group in ipairs(packages_group[group]) do
+ cprint(" ${yellow}%s${clear} %s %s ${dim}%s", idx == 1 and "->" or " or", package_in_group:displayname(), package_in_group:version_str() or "", package.get_configs_str(package_in_group))
+ packages_showed[tostring(package_in_group)] = true
+ end
+ packages_group[group] = nil
+ else
+ cprint(" ${yellow}->${clear} %s %s ${dim}%s", instance:displayname(), instance:version_str() or "", package.get_configs_str(instance))
+ packages_showed[tostring(instance)] = true
end
- packages_group[group] = nil
- else
- cprint(" ${yellow}->${clear} %s %s ${dim}%s", instance:displayname(), instance:version_str() or "", package.get_configs_str(instance))
- packages_showed[tostring(instance)] = true
end
end
end
+ end, answer = function ()
+ cprint("please input: ${bright}y${clear} (y/n/m)")
+ io.flush()
+ return (io.read() or "false"):trim()
+ end})
+
+ -- modify to select 3rd packages?
+ if result == "m" then
+ packages_modified = _get_confirm_from_3rd(packages)
+ result = nil
+ else
+ -- get confirm result
+ result = option.boolean(result)
+ if type(result) ~= "boolean" then
+ result = true
+ end
end
- end})
- return confirm
+ end
+ return result, packages_modified
end
-- install packages
@@ -423,7 +555,8 @@ function main(requires, opt)
end
-- get user confirm
- if not _get_confirm(packages_install) then
+ local confirm, packages_modified = _get_confirm(packages_install)
+ if not confirm then
local packages_must = {}
for _, instance in ipairs(packages_install) do
if not instance:is_optional() then
@@ -438,6 +571,15 @@ function main(requires, opt)
end
end
+ -- some packages are modified? we need fix packages list and all deps
+ if packages_modified then
+ order_packages = {}
+ _replace_packages(packages, packages_modified)
+ installdeps = _get_package_installdeps(packages)
+ _sort_packages_for_installdeps(packages, installdeps, order_packages)
+ packages = table.unique(order_packages)
+ end
+
-- sort package urls
_sort_packages_urls(packages_download)