diff options
| author | OpportunityLiu <[email protected]> | 2019-06-05 14:18:10 +0800 |
|---|---|---|
| committer | OpportunityLiu <[email protected]> | 2019-06-06 14:37:22 +0800 |
| commit | e9b11611ea2c2c2c892938deee37797a5d10d296 (patch) | |
| tree | 1fd47b9747bf6db535ed817636ba6bf1481037d1 | |
| parent | 12671e1c0af4e86d1ee73ccd13ff35defde7dc4b (diff) | |
install script
| -rw-r--r-- | tests/modules/devel/git/test.lua | 21 | ||||
| -rw-r--r-- | xmake/actions/update/get_version.lua | 83 | ||||
| -rw-r--r-- | xmake/actions/update/main.lua | 165 | ||||
| -rw-r--r-- | xmake/actions/update/xmake.lua | 16 | ||||
| -rw-r--r-- | xmake/modules/devel/git/asgiturl.lua | 66 | ||||
| -rw-r--r-- | xmake/scripts/run.vbs | 67 | ||||
| -rw-r--r-- | xmake/scripts/sudo.vbs | 15 | ||||
| -rw-r--r-- | xmake/scripts/update-script.bat | 7 | ||||
| -rw-r--r-- | xmake/scripts/update-script.sh | 5 |
9 files changed, 366 insertions, 79 deletions
diff --git a/tests/modules/devel/git/test.lua b/tests/modules/devel/git/test.lua new file mode 100644 index 000000000..ddcfc94b2 --- /dev/null +++ b/tests/modules/devel/git/test.lua @@ -0,0 +1,21 @@ +import("devel.git") + + +function test_asgiturl() + assert(git.asgiturl("http://github.com/a/b") == "https://github.com/a/b.git") + assert(git.asgiturl("http://github.com/a/b/") == "https://github.com/a/b.git") + assert(git.asgiturl("HTTP://github.com//a/b/") == "https://github.com/a/b.git") + assert(git.asgiturl("http://github.com//a/b/s") == nil) + assert(git.asgiturl("https://github.com/a/b") == "https://github.com/a/b.git") + assert(git.asgiturl("https://github.com/a/b.git") == "https://github.com/a/b.git") + assert(git.asgiturl("HTTPS://GITHUB.com/a/b.git.git") == "https://github.com/a/b.git.git") + + assert(git.asgiturl("github:a/b") == "https://github.com/a/b.git") + assert(git.asgiturl("github:a/b.git") == "https://github.com/a/b.git.git") + assert(git.asgiturl("GitHub://a/b/") == "https://github.com/a/b.git") + assert(git.asgiturl("github:a/b/c") == nil) +end + +function main() + test_asgiturl() +end
\ No newline at end of file diff --git a/xmake/actions/update/get_version.lua b/xmake/actions/update/get_version.lua new file mode 100644 index 000000000..2c45b6ae1 --- /dev/null +++ b/xmake/actions/update/get_version.lua @@ -0,0 +1,83 @@ +--!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 - 2019, TBOOX Open Source Group. +-- +-- @author OpportunityLiu +-- @file get_version.lua +-- + +-- imports +import("core.base.semver") +import("core.base.option") +import("core.base.task") +import("net.http") +import("devel.git") +import("net.fasturl") + +local official_sources = { + "https://github.com/xmake-io/xmake.git", + "https://gitlab.com/tboox/xmake.git", + "https://gitee.com/tboox/xmake.git" +} + +-- get version and url of provided xmakever +function main(xmakever) + xmakever = xmakever or "lastest" + + local commitish = nil + local custom_url = nil + local seg = xmakever:split('#', { plain = true, limit = 2, strict = true }) + if #seg == 2 then + if #seg[1] ~= 0 then + custom_url = seg[1] + end + commitish = seg[2] + else + if xmakever:find(':', 1, true) then + custom_url = xmakever + else + commitish = xmakever + end + end + + local urls = nil + if custom_url then + urls = { git.asgiturl(custom_url) or custom_url } + vprint("using custom source: %s ..", urls[1] ) + else + urls = official_sources + end + commitish = (commitish and #commitish > 0) and commitish or "lastest" + + -- sort urls + if #urls > 1 then + fasturl.add(urls) + urls = fasturl.sort(urls) + end + + -- get version + local version = nil + local tags, branches + for _, url in ipairs(urls) do + tags, branches = git.refs(url) + if tags or branches then + version = semver.select(commitish, tags or {}, tags or {}, branches or {}) + break + end + end + + return (urls == official_sources), urls, (version or "master"), tags, branches +end + diff --git a/xmake/actions/update/main.lua b/xmake/actions/update/main.lua index 108468a21..701c56b5c 100644 --- a/xmake/actions/update/main.lua +++ b/xmake/actions/update/main.lua @@ -28,15 +28,16 @@ import("net.fasturl") import("core.base.privilege") import("privilege.sudo") import("actions.require.impl.environment", {rootdir = os.programdir()}) +import("get_version") --- run cmd with privilege -function _sudo(cmd) +-- run program with privilege +function _sudo_v(program, params) -- attempt to install directly - try + return try { function () - os.vrun(cmd) + os.vrunv(program, params) return true end, @@ -53,7 +54,7 @@ function _sudo(cmd) local ok = try { function () - os.vrun(cmd) + os.vrunv(program, params) return true end } @@ -62,13 +63,14 @@ function _sudo(cmd) privilege.store() -- ok? - if ok then - return true + if ok then + return true end end -- show tips - cprint("\r${bright color.error}error: ${clear}run `%s` failed, may permission denied!", cmd) + local command = program .. " " ..os.args(params) + cprint("\r${bright color.error}error: ${clear}run `%s` failed, may permission denied!", command) -- continue to install with administrator permission? if sudo.has() then @@ -76,7 +78,7 @@ function _sudo(cmd) -- confirm to install? local confirm = utils.confirm({default = true, description = "try continue to run `%s` with administrator permission again"}) if confirm then - sudo.vrun(cmd) + sudo.vrunv(program, params) return true end end @@ -85,34 +87,40 @@ function _sudo(cmd) } end +-- run program witn admin user +function _run_win_v(program, commands, admin) + local sudo_vbs = path.join(os.programdir(), "scripts", "run.vbs") + local temp_vbs = os.tmpfile() .. ".vbs" + os.cp(sudo_vbs, temp_vbs) + local params = table.join("/Nologo", temp_vbs, "W" .. (admin and "A" or "N") , program, commands) + local proc = process.openv("cscript", params) + if proc then process.close(proc) end + return proc ~= nil +end + -- do uninstall function _uninstall() if is_host("windows") then local uninstaller = path.join(os.programdir(), "uninstall.exe") if os.isfile(uninstaller) then -- UAC on win7 + local params = option.get("quiet") and { "/S" } or {} if winos:version():gt("winxp") then - local proc = process.openv("cscript", {path.join(os.programdir(), "scripts", "sudo.vbs"), uninstaller}) - if proc ~= nil then - process.close(proc) - end + _run_win_v(uninstaller, params, true) else - local proc = process.open(uninstaller) - if proc ~= nil then - process.close(proc) - end + _run_win_v(uninstaller, params, false) end else raise("the uninstaller(%s) not found!", uninstaller) end else if os.programdir():startswith("/usr/") then - _sudo("rm -rf " .. os.programdir()) + _sudo_v("xmake", {"lua", "rm", os.programdir() }) if os.isfile("/usr/local/bin/xmake") then - _sudo("rm -f /usr/local/bin/xmake") + _sudo_v("xmake", {"lua", "rm", "/usr/local/bin/xmake" }) end if os.isfile("/usr/bin/xmake") then - _sudo("rm -f /usr/bin/xmake") + _sudo_v("xmake", {"lua", "rm", "/usr/bin/xmake" }) end else os.rm(os.programdir()) @@ -133,26 +141,23 @@ function _install(sourcedir, version) -- trace cprintf("\r${yellow} => ${clear}installing to %s .. ", installdir) - local ok = try + local ok = try { function () - -- install it + -- install it os.cd(sourcedir) if is_host("windows") then local installer = "xmake-" .. version .. ".exe" if os.isfile(installer) then + -- /D sets the default installation directory ($INSTDIR), overriding InstallDir and InstallDirRegKey. It must be the last parameter used in the command line and must not contain any quotes, even if the path contains spaces. Only absolute paths are supported. + local params = ("/D=" .. os.programdir()):split("%s", { strict = true }) + if option.get("quiet") then table.insert(params, 1, "/S") end -- need UAC? if winos:version():gt("winxp") then - local proc = process.openv("cscript", {path.join(os.programdir(), "scripts", "sudo.vbs"), installer}) - if proc ~= nil then - process.close(proc) - end + _run_win_v(installer, params, true) else - local proc = process.open(installer) - if proc ~= nil then - process.close(proc) - end + _run_win_v(installer, params, false) end else raise("the installer(%s) not found!", installer) @@ -169,7 +174,7 @@ function _install(sourcedir, version) end } } - + -- trace if ok then cprint("\r${yellow} => ${clear}install to %s .. ${green}ok ", installdir) @@ -191,6 +196,49 @@ function _install(sourcedir, version) end end +-- do install script +function _install_script(sourcedir) + cprintf("\r${yellow} => ${clear}install script to %s .. ", os.programdir()) + + local source = path.join(sourcedir, "xmake") + local dirname = path.filename(os.programdir()) + if dirname ~= "xmake" then + local target = path.join(sourcedir, dirname) + os.mv(source, target) + source = target + end + + local ok = try + { + function () + if is_host("windows") then + local script_original = path.join(os.programdir(), "scripts", "update-script.bat") + local script = os.tmpfile() .. ".bat" + os.cp(script_original, script) + local params = { "/c", script, os.programdir(), source } + os.tryrm(script_original .. ".bak") + local access = os.trymv(script_original, script_original .. ".bak") + return _run_win_v("cmd", params, not access) + else + local script = path.join(os.programdir(), "scripts", "update-script.sh") + return _sudo_v("sh", { script, os.programdir(), source }) + end + end, + catch + { + function (errors) + vprint(errors) + end + } + } + -- trace + if ok then + cprint("${color.success}${text.success}") + else + cprint("${color.failure}${text.failure}") + end +end + -- main function main() @@ -202,42 +250,28 @@ function main() -- trace cprint("${bright}uninstall ok!") - return + return end - -- enter environment + -- enter environment environment.enter() - -- sort main urls - local mainurls = {"https://github.com/xmake-io/xmake.git", - "https://gitlab.com/tboox/xmake.git", - "https://gitee.com/tboox/xmake.git"} - fasturl.add(mainurls) - mainurls = fasturl.sort(mainurls) - - -- get version - local tags = nil - local branches = nil - local version = nil - for _, url in ipairs(mainurls) do - tags, branches = git.refs(url) - if tags or branches then - version = semver.select(option.get("xmakever") or "lastest", tags or {}, tags or {}, branches or {}) - break - end - end - if not version then - version = "master" - end + local is_official, mainurls, version, tags, branches = get_version(option.get("xmakever")) -- has been installed? - if os.xmakever():eq(version) then + if is_official and xmake.version():eq(version) then cprint("${bright}xmake %s has been installed!", version) return end + local script_only = option.get("scriptonly") + -- get urls on windows - if is_host("windows") then + if is_host("windows") and not script_only then + if not is_official then + raise("not support to update from unofficial source on windows, missing '--scriptonly' flag?") + end + if version:find('.', 1, true) then mainurls = {format("https://github.com/xmake-io/xmake/releases/download/%s/xmake-%s.exe", version, version), format("https://qcloud.coding.net/u/waruqi/p/xmake-releases/git/raw/master/xmake-%s.exe", version), @@ -259,10 +293,16 @@ function main() end -- trace - print("update version: %s ..", version) + if is_official then + cprint("update version ${green}%s${clear} from official source ..", version) + else + cprint("update version ${green}%s${clear} from ${underline}%s${clear} ..", version, mainurls[1]) + end -- the download task local sourcedir = path.join(os.tmpdir(), "xmakesrc", version) + vprint("prepared to downlaod to temp dir %s ..", sourcedir) + local download_task = function () for idx, url in ipairs(mainurls) do cprintf("\r${yellow} => ${clear}downloading %s .. ", url) @@ -270,7 +310,8 @@ function main() { function () os.tryrm(sourcedir) - if not git.checkurl(url) then + -- all user provided urls are considered as git url since check has been performed in get_version + if is_official and not git.checkurl(url) then os.mkdir(sourcedir) http.download(url, path.join(sourcedir, path.filename(url))) else @@ -309,10 +350,14 @@ function main() process.asyncrun(download_task) end - -- leave environment + -- leave environment environment.leave() -- do install - _install(sourcedir, version) + if script_only then + _install_script(sourcedir) + else + _install(sourcedir, version) + end end diff --git a/xmake/actions/update/xmake.lua b/xmake/actions/update/xmake.lua index 5e42a9436..ae7f1a58f 100644 --- a/xmake/actions/update/xmake.lua +++ b/xmake/actions/update/xmake.lua @@ -30,7 +30,7 @@ task("update") -- set menu set_menu { -- usage - usage = "xmake update [options] [version]" + usage = "xmake update [options] [xmakever]" -- description , description = "Update and uninstall the xmake program." @@ -38,9 +38,17 @@ task("update") -- options , options = { - {nil, "uninstall", "k", nil, "Uninstall the current xmake program." } - , { } - , {nil, "xmakever", "v", nil, "The given xmake version. (e.g. ~2.2.3, dev, master)" } + {nil, "uninstall", "k", nil, "Uninstall the current xmake program." } + , { } + , {'s', "scriptonly", "k", nil, "Update script only" } + , {nil, "xmakever", "v", nil, "The given xmake version, or a git source (and branch). ", + "e.g.", + " from official source: ", + " lastest, ~2.2.3, dev, master", + " from custom source:", + " https://github.com/xmake-io/xmake", + " github:xmake-io/xmake#~2.2.3", + " git://github.com/xmake-io/xmake.git#master" } } } diff --git a/xmake/modules/devel/git/asgiturl.lua b/xmake/modules/devel/git/asgiturl.lua new file mode 100644 index 000000000..2b8f5ea7e --- /dev/null +++ b/xmake/modules/devel/git/asgiturl.lua @@ -0,0 +1,66 @@ +--!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 - 2019, TBOOX Open Source Group. +-- +-- @author OpportunityLiu +-- @file asgiturl.lua +-- + +-- imports +import("checkurl") + +local custom_protocol = { + ["github:"] = "https://github.com" +, ["gitlab:"] = "https://gitlab.com" +, ["gitee:"] = "https://gitee.com" +, ["bitbucket:"] = "https://bitbucket.org" +} + +-- try to parse given url as a git url +-- +-- @param url url can be transformed to a git url +-- +-- @return a git url or nil, if failed +-- + +function main(url) + url = url:trim() + assert(#url > 0) + + -- safe because all custom_protocol supports https + local lower = url:lower() + local n_url = url + if lower:startswith("http://") then + n_url = "https" .. url:sub(#"http" + 1) + lower = n_url:lower() + end + + for k, v in pairs(custom_protocol) do + if lower:startswith(k) then + local data = n_url:sub(#k + 1):split("/") + if #data ~= 2 then return nil end + return v .. "/" .. data[1] .. "/" .. data[2] .. ".git" + elseif lower:startswith(v) then + local data = n_url:sub(#v + 1):split("/") + if #data ~= 2 then return nil end + return v .. "/" .. data[1] .. "/" .. (data[2]:endswith(".git") and data[2] or (data[2] .. ".git")) + end + end + + if checkurl(url) then + return url + end +end + diff --git a/xmake/scripts/run.vbs b/xmake/scripts/run.vbs new file mode 100644 index 000000000..24fa86c4a --- /dev/null +++ b/xmake/scripts/run.vbs @@ -0,0 +1,67 @@ +Set UAC = CreateObject("Shell.Application") + +Const PROCESS = "xmake.exe" + +If WScript.Arguments.count < 2 Then + WScript.echo "Help: run <flag> <command> [args]" + WScript.echo " flags:" + WScript.echo " N - normal" + WScript.echo " A - run as admin" + WScript.echo " W - wait xmake to exit" + WScript.echo " You should use 'N' if no speical flags needed" + WScript.echo " e.g.: run WA xmake-install.exe /Q" +Else + Dim flags + Dim program + flags = UCase(WScript.arguments(0)) + program = WScript.arguments(1) + + Dim verb + Dim wait + If InStr(flags, "A") <> 0 Then + verb = "runas" + Else + verb = "open" + End If + + If InStr(flags, "W") <> 0 Then + Dim counter + counter = 0 + Dim sQuery + sQuery = "select * from win32_process where name='" & PROCESS & "'" + Do + Set SVC = getobject("winmgmts:root\cimv2") + Set cproc = SVC.execquery(sQuery) + iniproc = cproc.count + counter = counter + 1 + If counter >= 20 Then + WScript.echo "xmake still hasn't exited after 10 seconds, aborting..." + WScript.quit 1 + End If + If iniproc <> 0 Then + WScript.echo "Waiting for xmake to exit..." + wscript.sleep 500 + End If + Loop Until iniproc = 0 + + Set cproc = Nothing + Set SVC = Nothing + End If + + Dim ucCount + Dim args + args = "" + For ucCount = 2 To (WScript.Arguments.count - 1) Step 1 + Dim carg + if InStr(WScript.Arguments(ucCount), " ") <> 0 Then + carg = """" & Replace(WScript.Arguments(ucCount), """", """""") & """" + ElseIf Len(WScript.Arguments(ucCount)) = 0 Then + carg = """""" + Else + carg = WScript.Arguments(ucCount) + End If + args = args & " " & carg + Next + + UAC.ShellExecute program, args, "", verb, 1 +End If diff --git a/xmake/scripts/sudo.vbs b/xmake/scripts/sudo.vbs deleted file mode 100644 index 9bc71637c..000000000 --- a/xmake/scripts/sudo.vbs +++ /dev/null @@ -1,15 +0,0 @@ -Set UAC = CreateObject("Shell.Application") -Set Shell = CreateObject("WScript.Shell") -If WScript.Arguments.count < 1 Then - WScript.echo "Help: sudo <command> [args]" -ElseIf WScript.Arguments.count = 1 Then - UAC.ShellExecute WScript.arguments(0), "", "", "runas", 1 -Else - Dim ucCount - Dim args - args = NULL - For ucCount = 1 To (WScript.Arguments.count - 1) Step 1 - args = args & " " & WScript.Arguments(ucCount) - Next - UAC.ShellExecute WScript.arguments(0), args, "", "runas", 5 -End If diff --git a/xmake/scripts/update-script.bat b/xmake/scripts/update-script.bat new file mode 100644 index 000000000..f0df7c1bd --- /dev/null +++ b/xmake/scripts/update-script.bat @@ -0,0 +1,7 @@ +@echo off + +echo Removing old files +cd "%~1" +del actions core includes languages modules platforms plugins repository rules scripts templates themes /S /Q /F >nul +echo Copying from temp directory to "%~1" +xcopy "%~2" "%~1" /S /Y /Q >nul
\ No newline at end of file diff --git a/xmake/scripts/update-script.sh b/xmake/scripts/update-script.sh new file mode 100644 index 000000000..9e79ec71a --- /dev/null +++ b/xmake/scripts/update-script.sh @@ -0,0 +1,5 @@ + + +cd "$1" +rm actions core includes languages modules platforms plugins repository rules scripts templates themes -rf +cp "$2" "$1/.." -rf
\ No newline at end of file |
