diff options
| author | ruki <[email protected]> | 2021-08-19 22:21:53 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-08-19 22:21:53 +0800 |
| commit | 9c096fc45a4fb8ac817eb48ab8e762e2b41ab259 (patch) | |
| tree | bebf40a98ed31b8b7b94231976a26637614b80a1 | |
| parent | 69da74c43e934650eb797ec51f6b7c91fd419642 (diff) | |
| parent | 0eac4a64692796d99a1a30f206a2d21463e0acf6 (diff) | |
Merge pull request #1587 from xmake-io/requireslock
Support xmake-requires.lock to lock all required packages
23 files changed, 667 insertions, 128 deletions
diff --git a/core/src/xmake/semver/select.c b/core/src/xmake/semver/select.c index 221baf46d..395dc6f37 100644 --- a/core/src/xmake/semver/select.c +++ b/core/src/xmake/semver/select.c @@ -68,7 +68,7 @@ static tb_bool_t xm_semver_select_from_versions_tags1(lua_State* lua, tb_int_t f lua_pushstring(lua, top.raw); lua_setfield(lua, -2, "version"); - lua_pushstring(lua, fromidx == 2? "versions" : "tags"); + lua_pushstring(lua, fromidx == 2? "version" : "tag"); lua_setfield(lua, -2, "source"); // exit the popped semver @@ -92,7 +92,7 @@ static tb_bool_t xm_semver_select_from_versions_tags2(lua_State* lua, tb_int_t f lua_createtable(lua, 0, 2); lua_pushstring(lua, source_str); lua_setfield(lua, -2, "version"); - lua_pushstring(lua, fromidx == 2? "versions" : "tags"); + lua_pushstring(lua, fromidx == 2? "version" : "tag"); lua_setfield(lua, -2, "source"); return tb_true; } @@ -119,7 +119,7 @@ static tb_bool_t xm_semver_select_from_branches(lua_State* lua, tb_int_t fromidx lua_pushlstring(lua, source_str, source_len); lua_setfield(lua, -2, "version"); - lua_pushstring(lua, "branches"); + lua_pushstring(lua, "branch"); lua_setfield(lua, -2, "source"); // ok @@ -162,7 +162,7 @@ static tb_bool_t xm_semver_select_latest_from_versions_tags(lua_State* lua, tb_i lua_pushstring(lua, top.raw); lua_setfield(lua, -2, "version"); - lua_pushstring(lua, fromidx == 2? "versions" : "tags"); + lua_pushstring(lua, fromidx == 2? "version" : "tag"); lua_setfield(lua, -2, "source"); // exit the popped semver diff --git a/tests/modules/semver/test.lua b/tests/modules/semver/test.lua index f39f3acde..5141f099c 100755 --- a/tests/modules/semver/test.lua +++ b/tests/modules/semver/test.lua @@ -10,21 +10,21 @@ end -- test select version function test_semver_select(t) - _check_semver_select(t, {"1.5.1", "versions"} + _check_semver_select(t, {"1.5.1", "version"} , ">=1.5.0 <1.6.0" , {"1.4.0", "1.5.0", "1.5.1"}) - _check_semver_select(t, {"1.5.1", "versions"} + _check_semver_select(t, {"1.5.1", "version"} , "^1.5.0" ,{"1.4.0", "1.5.0", "1.5.1"}) - _check_semver_select(t, {"master", "branches"} + _check_semver_select(t, {"master", "branch"} , "master" , {"1.4.0", "1.5.0", "1.5.1"} , {"v1.2.0", "v1.6.0"} , {"master", "dev"}) - _check_semver_select(t, {"1.5.1", "versions"} + _check_semver_select(t, {"1.5.1", "version"} , "latest" , {"1.4.0", "1.5.0", "1.5.1"}) end diff --git a/tests/projects/package/multiconfig/xmake-requires.lock b/tests/projects/package/multiconfig/xmake-requires.lock new file mode 100644 index 000000000..e8621f5b3 --- /dev/null +++ b/tests/projects/package/multiconfig/xmake-requires.lock @@ -0,0 +1,41 @@ +{ + __meta__ = { + version = "1.0" + }, + ["zlib#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + arch = "x86_64", + buildhash = "b76a297309d14c09b42cfe3927260a51", + name = "zlib", + plat = "macosx", + repo = { + branch = "master", + commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "1.2.11" + }, + ["zlib~debug#d72a8a937b694e449bce540c8eb65a8a"] = { + arch = "x86_64", + buildhash = "e6a6fa6a86ad4fc7ae3c2cf7c60cc084", + name = "zlib", + plat = "macosx", + repo = { + branch = "master", + commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "1.2.11" + }, + ["zlib~shared#b286744a1898416faad2e5cab0104b2f"] = { + arch = "x86_64", + buildhash = "8e5b898b0f344715bac89cc6a1577506", + name = "zlib", + plat = "macosx", + repo = { + branch = "master", + commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "1.2.11" + } +}
\ No newline at end of file diff --git a/tests/projects/package/multiconfig/xmake.lua b/tests/projects/package/multiconfig/xmake.lua index 09121e8d2..7aa2bdffb 100644 --- a/tests/projects/package/multiconfig/xmake.lua +++ b/tests/projects/package/multiconfig/xmake.lua @@ -2,6 +2,7 @@ add_requires("zlib", {system = false}) add_requires("zlib", {system = false}) -- test repeat requires add_requires("zlib~debug", {system = false, debug = true}) add_requires("zlib~shared", {system = false, configs = {shared = true}, alias = "zlib_shared"}) +set_policy("package.requires_lock", true) target("test1") set_kind("binary") diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock new file mode 100644 index 000000000..9509b8501 --- /dev/null +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -0,0 +1,149 @@ +{ + __meta__ = { + version = "1.0" + }, + ["autoconf#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + arch = "x86_64", + buildhash = "01974c48f52d4d658f58852351743754", + name = "autoconf", + plat = "macosx", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "2.69" + }, + ["automake#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + arch = "x86_64", + buildhash = "7a090c93706241f983f0d821a162e8a5", + name = "automake", + plat = "macosx", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "1.16.1" + }, + ["cmake#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + arch = "x86_64", + buildhash = "a6d18f8c0bf347d980f8bb762583c91a", + name = "cmake", + plat = "macosx", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "3.21.0" + }, + ["gmp#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + arch = "x86_64", + buildhash = "7dd9c224447e46698ac73d29f58b1d73", + name = "gmp", + plat = "macosx", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "6.2.1" + }, + ["libisl 0.22#3dd996fa365042e39791030c4e1cad52"] = { + arch = "x86_64", + buildhash = "f649e1fb365e442e8f79f372fd91483b", + name = "libisl", + plat = "macosx", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "0.22" + }, + ["libogg#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + arch = "arm", + buildhash = "d894fc29f2fb4c45a0f48bc2c6ece273", + name = "libogg", + plat = "cross", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "v1.3.4" + }, + ["libplist#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + arch = "arm", + buildhash = "0c01b22920be4876b1de74629194eb8f", + name = "libplist", + plat = "cross", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "2.2.0" + }, + ["libtool#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + arch = "x86_64", + buildhash = "64584ec84a4743ecb740b598b263ffa6", + name = "libtool", + plat = "macosx", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "2.4.6" + }, + ["m4#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + arch = "x86_64", + buildhash = "fd0e83e5759b442a970327ebb1c89793", + name = "m4", + plat = "macosx", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "1.4.19" + }, + ["muslcc#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + arch = "x86_64", + buildhash = "11062c09ebeb484594488ad73ddbcd1f", + name = "muslcc", + plat = "macosx", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "20210202" + }, + ["pkg-config#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + arch = "x86_64", + buildhash = "84fd7f9b9f7a47709512cfc85cd9e5f7", + name = "pkg-config", + plat = "macosx", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "0.29.2" + }, + ["zlib#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + arch = "arm", + buildhash = "be90a245b8bb48e6b08a1a15bdcad467", + name = "zlib", + plat = "cross", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "1.2.11" + } +}
\ No newline at end of file diff --git a/tests/projects/package/toolchain_muslcc/xmake.lua b/tests/projects/package/toolchain_muslcc/xmake.lua index bf5e98e8c..b111d5976 100644 --- a/tests/projects/package/toolchain_muslcc/xmake.lua +++ b/tests/projects/package/toolchain_muslcc/xmake.lua @@ -4,6 +4,9 @@ add_rules("mode.debug", "mode.release") set_plat("cross") set_arch("arm") +-- lock requires +set_policy("package.requires_lock", true) + -- add library packages -- for testing zlib/xmake, libplist/autoconf, libogg/cmake add_requires("zlib", "libogg", {system = false}) diff --git a/xmake/actions/require/main.lua b/xmake/actions/require/main.lua index eb0e2014e..41b9a7eac 100644 --- a/xmake/actions/require/main.lua +++ b/xmake/actions/require/main.lua @@ -118,7 +118,7 @@ function main() scan(option.get("requires")) - -- install and update all outdated package dependencies by default if no arguments + -- install and upgrade all outdated package dependencies by default if no arguments else install(option.get("requires")) end diff --git a/xmake/actions/require/xmake.lua b/xmake/actions/require/xmake.lua index a9d4db32c..f33188f77 100644 --- a/xmake/actions/require/xmake.lua +++ b/xmake/actions/require/xmake.lua @@ -72,6 +72,7 @@ task("require") , {'s', "search", "k", nil, "Search for the given packages from repositories.", "e.g.", " $ xmake require --search tbox" } + , {nil, "upgrade", "k", nil, "Upgrade the installed packages." } , {nil, "uninstall", "k", nil, "Uninstall the installed packages.", "e.g.", " $ xmake require --uninstall", diff --git a/xmake/core/base/serialize.lua b/xmake/core/base/serialize.lua index 99486bf8c..a2d7b9ff9 100644 --- a/xmake/core/base/serialize.lua +++ b/xmake/core/base/serialize.lua @@ -123,7 +123,8 @@ function serialize._maketable(obj, opt, level, pathsegs, reftab) local sformat = opt.indentstr and "[%q] = %s" or "[%q]=%s" local nformat = opt.indentstr and "[%s] = %s" or "[%s]=%s" local keywords = serialize._keywords() - for k, v in pairs(serialized) do + local makepairs = opt.orderkeys and table.orderpairs or pairs + for k, v in makepairs(serialized) do local format -- serialize key if type(k) == "string" then diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua index c86a90988..01a6a4692 100644 --- a/xmake/core/base/table.lua +++ b/xmake/core/base/table.lua @@ -317,6 +317,21 @@ function table.orderkeys(tab) return keys end +-- order key/value iterator +-- +-- for k, v in table.orderpairs(t) do +-- TODO +-- end +function table.orderpairs(t) + local orderkeys = table.orderkeys(t) + local i = 1 + return function (t, k) + k = orderkeys[i] + i = i + 1 + return k, t[k] + end, t, nil +end + -- get values of a table function table.values(tab) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index fefa4eb17..f7b2b7884 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -115,10 +115,10 @@ function _instance:plat() return os.subhost() end local requireinfo = self:requireinfo() - if not plat and requireinfo and requireinfo.plat then + if requireinfo and requireinfo.plat then return requireinfo.plat end - return self:get("plat") or package._target_plat() + return package._target_plat() end -- get the architecture of package @@ -145,7 +145,7 @@ function _instance:targetarch() if requireinfo and requireinfo.arch then return requireinfo.arch end - return self:get("arch") or package._target_arch() + return package._target_arch() end -- get the build mode @@ -855,22 +855,7 @@ function _instance:version_str() return self._VERSION_STR end --- get branch version -function _instance:branch() - return self._BRANCH -end - --- get tag version -function _instance:tag() - return self._TAG -end - --- is git ref? -function _instance:gitref() - return self:branch() or self:tag() -end - --- set the version, source: branches, tags, versions +-- set the version, source: branch, tag, version function _instance:version_set(version, source) -- save the semver version @@ -880,17 +865,31 @@ function _instance:version_set(version, source) end -- save branch and tag - if source == "branches" then + if source == "branch" then self._BRANCH = version - elseif source == "tags" then + elseif source == "tag" then self._TAG = version end - -- save source and version string - self._SOURCE = source + -- save version string self._VERSION_STR = version end +-- get branch version +function _instance:branch() + return self._BRANCH +end + +-- get tag version +function _instance:tag() + return self._TAG +end + +-- is git ref? +function _instance:gitref() + return self:branch() or self:tag() +end + -- get the require info function _instance:requireinfo() return self._REQUIREINFO @@ -1703,8 +1702,8 @@ function package.apis() -- package.set_xxx "package.set_urls" , "package.set_kind" - , "package.set_plat" - , "package.set_arch" + , "package.set_plat" -- deprecated + , "package.set_arch" -- deprecated , "package.set_license" , "package.set_homepage" , "package.set_description" diff --git a/xmake/core/project/policy.lua b/xmake/core/project/policy.lua index 7040182a2..c624aed96 100644 --- a/xmake/core/project/policy.lua +++ b/xmake/core/project/policy.lua @@ -44,7 +44,9 @@ function policy.policies() -- we can compile the source files for each target in parallel ["build.across_targets_in_parallel"] = {description = "Enable compile the source files for each target in parallel.", default = true, type = "boolean"}, -- we need enable longpaths when building target or installing package - ["platform.longpaths"] = {description = "Enable long paths when building target or installing package on windows.", default = false, type = "boolean"} + ["platform.longpaths"] = {description = "Enable long paths when building target or installing package on windows.", default = false, type = "boolean"}, + -- lock required packages + ["package.requires_lock"] = {description = "Enable xmake-requires.lock to lock required packages.", default = false, type = "boolean"} } policy._POLICIES = policies end diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index fafc254bf..91982e64a 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -1023,6 +1023,16 @@ function project.requireconfs_str() return requireconfs_str, requireconfs_extra end +-- get requires lockfile +function project.requireslock() + return path.join(project.directory(), "xmake-requires.lock") +end + +-- get the format version of requires lockfile +function project.requireslock_version() + return "1.0" +end + -- get the given rule function project.rule(name) return project.rules()[name] diff --git a/xmake/core/sandbox/modules/import/core/base/semver.lua b/xmake/core/sandbox/modules/import/core/base/semver.lua index edaf61470..eadcfb702 100644 --- a/xmake/core/sandbox/modules/import/core/base/semver.lua +++ b/xmake/core/sandbox/modules/import/core/base/semver.lua @@ -80,7 +80,7 @@ end -- local version, source = semver.select(">=1.5.0 <1.6", {"1.5.0", "1.5.1"}, {"v1.5.0", ..}, {"master", "dev"}) -- -- @version the selected version number --- @source the version source, e.g. versions, tags, branchs +-- @source the version source, e.g. version, tag, branch -- function sandbox_core_base_semver.select(range, versions, tags, branches) local verinfo, errors = semver.select(range, table.wrap(versions), table.wrap(tags), table.wrap(branches)) diff --git a/xmake/core/sandbox/modules/import/core/package/repository.lua b/xmake/core/sandbox/modules/import/core/package/repository.lua index 4dc00a0ed..5d8406094 100644 --- a/xmake/core/sandbox/modules/import/core/package/repository.lua +++ b/xmake/core/sandbox/modules/import/core/package/repository.lua @@ -29,20 +29,13 @@ local repository = require("package/repository") local raise = require("sandbox/modules/raise") local import = require("sandbox/modules/import") --- get repository directory -function sandbox_core_package_repository.directory(is_global) - return repository.directory(is_global) -end - --- get repository url from the given name -function sandbox_core_package_repository.get(name, is_global) - return repository.get(name, is_global) -end +-- inherit some builtin interfaces +sandbox_core_package_repository.directory = repository.directory +sandbox_core_package_repository.get = repository.get +sandbox_core_package_repository.load = repository.load -- add repository url to the given name function sandbox_core_package_repository.add(name, url, branch, is_global) - - -- add it local ok, errors = repository.add(name, url, branch, is_global) if not ok then raise(errors) @@ -51,8 +44,6 @@ end -- remove repository from gobal or local directory function sandbox_core_package_repository.remove(name, is_global) - - -- remove it local ok, errors = repository.remove(name, is_global) if not ok then raise(errors) @@ -61,8 +52,6 @@ end -- clear all repositories from global or local directory function sandbox_core_package_repository.clear(is_global) - - -- clear all repositories local ok, errors = repository.clear(is_global) if not ok then raise(errors) diff --git a/xmake/core/sandbox/modules/import/core/project/project.lua b/xmake/core/sandbox/modules/import/core/project/project.lua index 694532527..34b5fa7ac 100644 --- a/xmake/core/sandbox/modules/import/core/project/project.lua +++ b/xmake/core/sandbox/modules/import/core/project/project.lua @@ -36,37 +36,39 @@ local package = require("package/package") local import = require("sandbox/modules/import") -- export some readonly interfaces -sandbox_core_project.get = project.get -sandbox_core_project.extraconf = project.extraconf -sandbox_core_project.rule = project.rule -sandbox_core_project.rules = project.rules -sandbox_core_project.toolchain = project.toolchain -sandbox_core_project.toolchains = project.toolchains -sandbox_core_project.target = project.target -sandbox_core_project.targets = project.targets -sandbox_core_project.ordertargets = project.ordertargets -sandbox_core_project.option = project.option -sandbox_core_project.options = project.options -sandbox_core_project.rootfile = project.rootfile -sandbox_core_project.allfiles = project.allfiles -sandbox_core_project.rcfiles = project.rcfiles -sandbox_core_project.directory = project.directory -sandbox_core_project.name = project.name -sandbox_core_project.modes = project.modes -sandbox_core_project.default_arch = project.default_arch -sandbox_core_project.allowed_modes = project.allowed_modes -sandbox_core_project.allowed_plats = project.allowed_plats -sandbox_core_project.allowed_archs = project.allowed_archs -sandbox_core_project.mtimes = project.mtimes -sandbox_core_project.version = project.version -sandbox_core_project.required_package = project.required_package -sandbox_core_project.required_packages = project.required_packages -sandbox_core_project.requires_str = project.requires_str -sandbox_core_project.requireconfs_str = project.requireconfs_str -sandbox_core_project.policy = project.policy -sandbox_core_project.tmpdir = project.tmpdir -sandbox_core_project.tmpfile = project.tmpfile -sandbox_core_project.is_loaded = project.is_loaded +sandbox_core_project.get = project.get +sandbox_core_project.extraconf = project.extraconf +sandbox_core_project.rule = project.rule +sandbox_core_project.rules = project.rules +sandbox_core_project.toolchain = project.toolchain +sandbox_core_project.toolchains = project.toolchains +sandbox_core_project.target = project.target +sandbox_core_project.targets = project.targets +sandbox_core_project.ordertargets = project.ordertargets +sandbox_core_project.option = project.option +sandbox_core_project.options = project.options +sandbox_core_project.rootfile = project.rootfile +sandbox_core_project.allfiles = project.allfiles +sandbox_core_project.rcfiles = project.rcfiles +sandbox_core_project.directory = project.directory +sandbox_core_project.name = project.name +sandbox_core_project.modes = project.modes +sandbox_core_project.default_arch = project.default_arch +sandbox_core_project.allowed_modes = project.allowed_modes +sandbox_core_project.allowed_plats = project.allowed_plats +sandbox_core_project.allowed_archs = project.allowed_archs +sandbox_core_project.mtimes = project.mtimes +sandbox_core_project.version = project.version +sandbox_core_project.required_package = project.required_package +sandbox_core_project.required_packages = project.required_packages +sandbox_core_project.requires_str = project.requires_str +sandbox_core_project.requireconfs_str = project.requireconfs_str +sandbox_core_project.requireslock = project.requireslock +sandbox_core_project.requireslock_version = project.requireslock_version +sandbox_core_project.policy = project.policy +sandbox_core_project.tmpdir = project.tmpdir +sandbox_core_project.tmpfile = project.tmpfile +sandbox_core_project.is_loaded = project.is_loaded -- check project options function sandbox_core_project.check() diff --git a/xmake/modules/devel/git/lastcommit.lua b/xmake/modules/devel/git/lastcommit.lua new file mode 100644 index 000000000..876812f86 --- /dev/null +++ b/xmake/modules/devel/git/lastcommit.lua @@ -0,0 +1,77 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file lastcommit.lua +-- + +-- imports +import("core.base.option") +import("lib.detect.find_tool") +import("net.proxy") + +-- get last commit in git repository +-- +-- @param opt the options, e.g. {repodir = ..} +-- +-- @return the last commit +-- +-- @code +-- +-- import("devel.git") +-- +-- local lastcommit = git.lastcommit({repodir = ..}) +-- +-- @endcode +-- +function main(opt) + + -- find git + local git = assert(find_tool("git"), "git not found!") + + -- init arguments + local argv = {"rev-parse", "HEAD"} + + -- trace + if option.get("verbose") then + print("%s %s", git.program, os.args(argv)) + end + + -- use proxy? + local envs + local proxy_conf = proxy.config(url) + if proxy_conf then + envs = {ALL_PROXY = proxy_conf} + end + + -- enter repository directory + local oldir = nil + if opt.repodir then + oldir = os.cd(opt.repodir) + end + + -- get last commit + local lastcommit = os.iorunv(git.program, argv, {envs = envs}) + if lastcommit then + lastcommit = lastcommit:trim() + end + + -- leave repository directory + if oldir then + os.cd(oldir) + end + return lastcommit +end diff --git a/xmake/modules/private/action/require/impl/install_packages.lua b/xmake/modules/private/action/require/impl/install_packages.lua index 7e83ae939..75ca4414e 100644 --- a/xmake/modules/private/action/require/impl/install_packages.lua +++ b/xmake/modules/private/action/require/impl/install_packages.lua @@ -30,6 +30,7 @@ import("actions.install", {alias = "action_install"}) import("actions.download", {alias = "action_download"}) import("net.fasturl") import("private.action.require.impl.package") +import("private.action.require.impl.lock_packages") import("private.action.require.impl.register_packages") -- sort packages urls @@ -600,6 +601,11 @@ function main(requires, opt) -- re-register and refresh all root packages to local cache, -- because there may be some missing optional dependencies reinstalled register_packages(packages) + + -- lock packages + if #packages_install > 0 then + lock_packages(packages) + end return packages end diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua new file mode 100644 index 000000000..18dabcac4 --- /dev/null +++ b/xmake/modules/private/action/require/impl/lock_packages.lua @@ -0,0 +1,64 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file lock_packages.lua +-- + +-- imports +import("core.project.project") +import("core.project.config") +import("devel.git") +import("private.action.require.impl.utils.filter") +import("private.action.require.impl.utils.requirekey") + +-- get locked package key +function _get_packagelock_key(instance) + local requireinfo = instance:requireinfo() + return requireinfo and requireinfo.requirekey +end + +-- lock package +function _lock_package(instance) + local result = {} + local repo = instance:repo() + result.name = instance:name() + result.plat = instance:plat() + result.arch = instance:arch() + result.version = instance:version_str() + result.buildhash = instance:buildhash() + result.branch = instance:branch() + result.tag = instance:tag() + if repo then + local lastcommit = git.lastcommit({repodir = repo:directory()}) + result.repo = {url = repo:url(), commit = lastcommit, branch = repo:branch()} + end + return result +end + +-- lock all required packages +function main(packages) + if project.policy("package.requires_lock") then + local results = {__meta__ = {}} + results.__meta__.version = project.requireslock_version() + for _, instance in ipairs(packages) do + local packagelock_key = _get_packagelock_key(instance) + results[packagelock_key] = _lock_package(instance) + end + io.writefile(project.requireslock(), string.serialize(results, {orderkeys = true})) + end +end + diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 612911429..5084d2d29 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -26,10 +26,12 @@ import("core.base.hashset") import("private.utils.progress") import("core.cache.memcache") import("core.project.project") +import("core.project.config") import("core.tool.toolchain") import("core.package.package", {alias = "core_package"}) import("devel.git") import("private.action.require.impl.repository") +import("private.action.require.impl.utils.requirekey", {alias = "_get_requirekey"}) -- get memcache function _memcache() @@ -193,13 +195,34 @@ function _load_package_from_project(packagename) end -- load package package from repositories -function _load_package_from_repository(packagename, reponame) - local packagedir, repo = repository.packagedir(packagename, reponame) +function _load_package_from_repository(packagename, opt) + local packagedir, repo = repository.packagedir(packagename, opt) if packagedir then return core_package.load_from_repository(packagename, repo, packagedir) end end +-- has locked requires? +function _has_locked_requires() + if not option.get("upgrade") then + return project.policy("package.requires_lock") and os.isfile(project.requireslock()) + end +end + +-- get locked requires +function _get_locked_requires(requirekey) + local requireslock = _memcache():get("requireslock") + if requireslock == nil then + if _has_locked_requires() then + requireslock = io.load(project.requireslock()) + end + _memcache():set("requireslock", requireslock or false) + end + if requireslock then + return requireslock[requirekey], requireslock.__meta__.version + end +end + -- sort package deps -- -- e.g. @@ -246,7 +269,19 @@ function _add_package_configurations(package) end -- select package version -function _select_package_version(package, requireinfo) +function _select_package_version(package, requireinfo, locked_requireinfo) + + -- get it from the locked requireinfo + if locked_requireinfo then + local version = locked_requireinfo.version + local source = "version" + if locked_requireinfo.branch then + source = "branch" + elseif locked_requireinfo.tag then + source = "tag" + end + return version, source + end -- exists urls? otherwise be phony package (only as package group) if #package:urls() > 0 then @@ -270,12 +305,12 @@ function _select_package_version(package, requireinfo) -- @see https://github.com/xmake-io/xmake/issues/930 -- https://github.com/xmake-io/xmake/issues/1009 version = require_version - source = "versions" + source = "version" elseif #package:versions() > 0 then -- select version? version, source = try { function () return semver.select(require_version, package:versions()) end } end if not version and has_giturl and not require_version:find('.', 1, true) then -- select branch? - version, source = require_version ~= "latest" and require_version or "master", "branches" + version, source = require_version ~= "latest" and require_version or "master", "branch" end if not version then raise("package(%s): version(%s) not found!", package:name(), require_version) @@ -477,26 +512,19 @@ end -- get package key function _get_packagekey(packagename, requireinfo, version) - local key = packagename .. "/" .. (version or requireinfo.version) - if requireinfo.plat then - key = key .. "/" .. requireinfo.plat - end - if requireinfo.arch then - key = key .. "/" .. requireinfo.arch - end - if requireinfo.label then - key = key .. "/" .. requireinfo.label - end - local configs = requireinfo.configs - if configs then - local configs_order = {} - for k, v in pairs(configs) do - table.insert(configs_order, k .. "=" .. tostring(v)) - end - table.sort(configs_order) - key = key .. ":" .. string.serialize(configs_order, true) - end - return key + return _get_requirekey(requireinfo, {name = packagename, + plat = requireinfo.plat, + arch = requireinfo.arch, + version = version or requireinfo.version}) +end + +-- get locked package key +function _get_packagelock_key(requireinfo) + local plat = config.plat() or os.subhost() + local arch = config.arch() or os.subarch() + local requirestr = requireinfo.originstr + local key = _get_requirekey(requireinfo, {hash = true, plat = plat, arch = arch}) + return string.format("%s#%s", requirestr, key) end -- inherit some builtin configs of parent package if these config values are not default value @@ -610,6 +638,19 @@ function _load_package(packagename, requireinfo, opt) requireinfo.label = splitinfo[2] end + -- sve requirekey + local requirekey = _get_packagelock_key(requireinfo) + requireinfo.requirekey = requirekey + + -- get locked requireinfo + local locked_requireinfo, requireslock_version + if _has_locked_requires() then + locked_requireinfo, requireslock_version = _get_locked_requires(requirekey) + if requireslock_version and semver.compare(project.requireslock_version(), requireslock_version) < 0 then + locked_requireinfo = nil + end + end + -- load package from project first local package if os.isfile(os.projectfile()) then @@ -619,7 +660,8 @@ function _load_package(packagename, requireinfo, opt) -- load package from repositories local from_repo = false if not package then - package = _load_package_from_repository(packagename, requireinfo.reponame) + package = _load_package_from_repository(packagename, { + name = requireinfo.reponame, locked_repo = locked_requireinfo and locked_requireinfo.repo}) if package then from_repo = true end @@ -652,7 +694,7 @@ function _load_package(packagename, requireinfo, opt) _finish_requireinfo(requireinfo, package) -- select package version - local version, source = _select_package_version(package, requireinfo) + local version, source = _select_package_version(package, requireinfo, locked_requireinfo) if version then package:version_set(version, source) end @@ -712,6 +754,11 @@ function _load_package(packagename, requireinfo, opt) on_load(package) end + -- check build hash + if locked_requireinfo and locked_requireinfo.buildhash ~= package:buildhash() then + wprint("package(%s): buildhash is not matched in xmake-requires.lock", package:displayname(), locked_requireinfo.buildhash, package:buildhash()) + end + -- load environments from the manifest to enable the environments of on_install() package:envs_load() diff --git a/xmake/modules/private/action/require/impl/repository.lua b/xmake/modules/private/action/require/impl/repository.lua index 4dbf44e52..528aebc54 100644 --- a/xmake/modules/private/action/require/impl/repository.lua +++ b/xmake/modules/private/action/require/impl/repository.lua @@ -19,8 +19,64 @@ -- -- imports +import("core.base.option") import("core.base.global") +import("core.project.config") import("core.package.repository") +import("devel.git") + +-- get package directory from the locked repository +function _get_packagedir_from_locked_repo(packagename, locked_repo) + + -- find global repository directory + local repodir_global + for _, repo in ipairs(repositories()) do + if locked_repo.url == repo:url() and locked_repo.branch == repo:branch() then + repodir_global = repo:directory() + break + end + end + local reponame = hash.uuid(locked_repo.url):gsub("%-", ""):lower() .. ".lock" + + -- clone repository to local + local repodir_local = path.join(config.directory(), "repositories", reponame) + if not os.isdir(repodir_local) then + if repodir_global then + git.clone(repodir_global, {verbose = option.get("verbose"), outputdir = repodir_local}) + elseif global.get("network") ~= "private" then + git.clone(locked_repo.url, {verbose = option.get("verbose"), branch = locked_repo.branch, outputdir = repodir_local}) + else + wprint("we cannot lock repository(%s) in private network mode!", locked_repo.url) + return + end + end + + -- try checkout to the given commit + local ok = try {function () git.checkout(locked_repo.commit, {verbose = option.get("verbose"), repodir = repodir_local}); return true end} + if not ok then + if global.get("network") ~= "private" then + -- pull the latest commit + git.pull({verbose = option.get("verbose"), remote = locked_repo.url, branch = locked_repo.branch, repodir = repodir_local}) + -- re-checkout to the given commit + ok = try {function () git.checkout(locked_repo.commit, {verbose = option.get("verbose"), repodir = repodir_local}); return true end} + else + wprint("we cannot lock repository(%s) in private network mode!", locked_repo.url) + return + end + end + + -- find package directory + local foundir + if ok then + local dir = path.join(repodir_local, "packages", packagename:sub(1, 1), packagename) + if os.isdir(dir) and os.isfile(path.join(dir, "xmake.lua")) then + local repo = repository.load(reponame, locked_repo.url, locked_repo.branch, false) + foundir = {dir, repo} + vprint("lock package(%s) in %s from repository(%s)/%s", packagename, dir, locked_repo.url, locked_repo.commit) + end + end + return foundir +end -- get all repositories function repositories() @@ -48,34 +104,53 @@ function pulled() end -- get package directory from repositories -function packagedir(packagename, reponame) +function packagedir(packagename, opt) -- strip trailng ~tag, e.g. zlib~debug + opt = opt or {} packagename = packagename:lower() if packagename:find('~', 1, true) then packagename = packagename:gsub("~.+$", "") end - -- get it from cache it - local packagedirs = _g._PACKAGEDIRS or {} - local foundir = packagedirs[packagename] - if foundir then - return foundir[1], foundir[2] + -- get cache key + local reponame = opt.name + local cachekey = packagename + local locked_repo = opt.locked_repo + if locked_repo then + cachekey = cachekey .. locked_repo.url .. locked_repo.commit .. (locked_repo.branch or "") + end + local packagedirs = _g._PACKAGEDIRS + if not packagedirs then + packagedirs = {} + _g._PACKAGEDIRS = packagedirs end - -- find the package directory from repositories - for _, repo in ipairs(repositories()) do - local dir = path.join(repo:directory(), "packages", packagename:sub(1, 1), packagename) - if os.isdir(dir) and os.isfile(path.join(dir, "xmake.lua")) and (not reponame or reponame == repo:name()) then - foundir = {dir, repo} - break + -- get the package directory + local foundir = packagedirs[cachekey] + if not foundir then + + -- find the package directory from the locked repository + if locked_repo then + local dir, repo = _get_packagedir_from_locked_repo(packagename, locked_repo) + if dir and repo then + foundir = {dir, repo} + end end + + -- find the package directory from repositories + if not foundir then + for _, repo in ipairs(repositories()) do + local dir = path.join(repo:directory(), "packages", packagename:sub(1, 1), packagename) + if os.isdir(dir) and os.isfile(path.join(dir, "xmake.lua")) and (not reponame or reponame == repo:name()) then + foundir = {dir, repo} + break + end + end + end + packagedirs[cachekey] = foundir or {} end - if foundir then - packagedirs[packagename] = foundir - _g._PACKAGEDIRS = packagedirs - return foundir[1], foundir[2] - end + return foundir[1], foundir[2] end -- get artifacts manifest from repositories diff --git a/xmake/modules/private/action/require/impl/utils/requirekey.lua b/xmake/modules/private/action/require/impl/utils/requirekey.lua new file mode 100644 index 000000000..b07e4d50d --- /dev/null +++ b/xmake/modules/private/action/require/impl/utils/requirekey.lua @@ -0,0 +1,57 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file requirekey.lua +-- + +-- get require key from requireinfo +function main(requireinfo, opt) + opt = opt or {} + local key = "" + if opt.name then + key = key .. "/" .. opt.name + end + if opt.plat then + key = key .. "/" .. opt.plat + end + if opt.arch then + key = key .. "/" .. opt.arch + end + if opt.version then + key = key .. "/" .. opt.version + end + if requireinfo.label then + key = key .. "/" .. requireinfo.label + end + if key:startswith("/") then + key = key:sub(2) + end + local configs = requireinfo.configs + if configs then + local configs_order = {} + for k, v in pairs(configs) do + table.insert(configs_order, k .. "=" .. tostring(v)) + end + table.sort(configs_order) + key = key .. ":" .. string.serialize(configs_order, true) + end + if opt.hash then + return hash.uuid(key):gsub("%-", ""):lower() + else + return key + end +end diff --git a/xmake/modules/private/action/require/install.lua b/xmake/modules/private/action/require/install.lua index 821991dee..e27e627cb 100644 --- a/xmake/modules/private/action/require/install.lua +++ b/xmake/modules/private/action/require/install.lua @@ -76,7 +76,7 @@ function main(requires_raw) -- -- attempt to install git from the builtin-packages first if git not found -- - if git and not repository.pulled() then + if git and (not repository.pulled() or option.get("upgrade")) then task.run("repo", {update = true}) end |
