diff --git a/.appveyor.yml b/.appveyor.yml index 4b17152927e..48a726de39e 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -9,23 +9,33 @@ platform: - Win64 install: - - cmd: echo %CI% + - ps: ./scripts/get.ps1 -branch $env:APPVEYOR_REPO_BRANCH build_script: - - ps: Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-Webrequest "https://raw.githubusercontent.com/xmake-io/xmake/dev/scripts/get.ps1" -UseBasicParsing).Content)) -ArgumentList "dev" - - cmd: xmake --version - - cmd: xmake -P core - - cmd: set XMAKE_PROGRAM_DIR=%cd%\xmake - - cmd: core\build\xmake --version - - ps: Copy-Item -Force core\build\xmake.exe $HOME\xmake - - cmd: xmake lua -D tests\test.lua - -#on_success: -# - ps: $env:XMAKE_PROGRAM_DIR=$null -# - ps: Invoke-Expression (Get-Content scripts\getpb.ps1 | Out-String) + - ps: Get-Command xmake + - ps: xmake --version + - ps: xmake build --project=core + - ps: |- + Set-AppveyorBuildVariable -Name XMAKE_PROGRAM_DIR -Value $(Join-Path $(Get-Location) "xmake") + .\core\build\xmake.exe --version + Copy-Item -Force core\build\xmake.exe $(Get-Command xmake).Source after_build: - - ps: Copy-Item core\build\xmake.exe . + - ps: |- + Copy-Item .\core\build\xmake.exe .\xmake + Copy-Item .\*.md .\xmake + Compress-Archive -Path .\xmake -DestinationPath .\archive.zip -CompressionLevel Optimal + Push-AppveyorArtifact .\xmake\xmake.exe -FileName xmake.exe -DeploymentName "xmake-executable" + Push-AppveyorArtifact .\archive.zip -FileName xmake.zip -DeploymentName "xmake-archive" + +test_script: + - ps: xmake --version + - ps: |- + Add-AppveyorTest -Name "tests" -Framework "xmake-test" -FileName ./tests/test.lua -Outcome Running + $time = Measure-Command { + $results = xmake lua --verbose --diagnosis tests\test.lua 2>&1 + $outcome = if ($?) { "Passed" } else { "Failed" } + $stdout = [string]::Join("`n", $results) + } + Update-AppveyorTest -Name "tests" -Framework "xmake-test" -FileName ./tests/test.lua -Outcome $outcome -Duration $time.TotalMilliseconds -StdOut $stdout -artifacts: - - path: xmake.exe diff --git a/.gitignore b/.gitignore index 9dd2d123e46..cd7ecbe72af 100644 --- a/.gitignore +++ b/.gitignore @@ -41,4 +41,4 @@ core/.config.mak winenv xmake-ppa !xmake/actions/build -.vscode/* \ No newline at end of file +.vscode/ \ No newline at end of file diff --git a/scripts/get.ps1 b/scripts/get.ps1 index 4b186c23ffe..8bce6286142 100644 --- a/scripts/get.ps1 +++ b/scripts/get.ps1 @@ -4,129 +4,74 @@ param ( [string]$branch = "master", - [string]$version = "v2.2.6" + [string]$version = "v2.2.6", + [string]$installdir = $(Join-Path $(if($env:HOME) { $env:HOME } else { "C:\" }) 'xmake') ) -& { - - function myExit($code) { - if ($code -is [int] -and $code -ne 0) { - throw $Error[0] - } else { - break - } +function myExit($code) { + if ($code -is [int] -and $code -ne 0) { + throw $Error[0] + } else { + break } +} - function writeErrorTip($msg) { - Write-Host $msg -BackgroundColor Red -ForegroundColor White - } +function writeErrorTip($msg) { + Write-Host $msg -BackgroundColor Red -ForegroundColor White +} - function writeLogoLine($msg) { - Write-Host $msg -BackgroundColor White -ForegroundColor DarkBlue - } +function writeLogoLine($msg) { + Write-Host $msg -BackgroundColor White -ForegroundColor DarkBlue +} - function registerTabCompletion { - - function writeDataToFile($file) { - $encoding = [text.encoding]::UTF8 - if (Test-Path $file -PathType Leaf) { - #Create a stream reader to get the file's encoding and contents. - $sr = New-Object System.IO.StreamReader($file, $true) - [char[]] $buffer = new-object char[] 3 - $sr.Read($buffer, 0, 3) | Out-Null - $encoding = $sr.CurrentEncoding - $sr.Close() | Out-Null - - if ($(Get-Content $file) -imatch "Register-ArgumentCompleter -Native -CommandName xmake -ScriptBlock") { - Write-Host "Seems the tab completion of xmake has installed here..." - return - } - } +writeLogoLine ' _ ' +writeLogoLine ' __ ___ __ __ __ _| | ______ ' +writeLogoLine ' \ \/ / | \/ |/ _ | |/ / __ \ ' +writeLogoLine ' > < | \__/ | /_| | < ___/ ' +writeLogoLine ' /_/\_\_|_| |_|\__ \|_|\_\____| getter ' +writeLogoLine ' ' +writeLogoLine ' ' - try { - [IO.File]::AppendAllText($file, "`n", $encoding) - } catch { - writeErrorTip "Failed to append to profile!" - writeErrorTip "Please try again as administrator" - return - } - try { - $content = (Invoke-Webrequest 'https://raw.githubusercontent.com/xmake-io/xmake/master/scripts/register-completions.ps1' -UseBasicParsing).Content - } catch { - writeErrorTip 'Download failed!' - writeErrorTip 'Check your network or... the news of S3 break' - return - } - [IO.File]::AppendAllText($file, $content, $encoding) - [IO.File]::AppendAllText($file, "`n", $encoding) - } - $message = 'Tab completion service' - $question = 'Would you like to install tab completion service of xmake to your profile?' - - $choices = @( - (New-Object Management.Automation.Host.ChoiceDescription -ArgumentList @( - 'For &all users', - "Install for all users, writes to $($PROFILE.AllUsersAllHosts), admin privilege is needed.")), - (New-Object Management.Automation.Host.ChoiceDescription -ArgumentList @( - 'Just for &me', - "Install for current user, writes to $($PROFILE.CurrentUserAllHosts).")), - (New-Object Management.Automation.Host.ChoiceDescription -ArgumentList @( - 'Just for this &host', - "Install for current user current host, writes to $($PROFILE.CurrentUserCurrentHost).")), - (New-Object Management.Automation.Host.ChoiceDescription -ArgumentList @( - '&No', - "Do not install xmake's tab completion service.")) - ) - switch ($Host.UI.PromptForChoice($message, $question, $choices, 1)) { - 0 { writeDataToFile($PROFILE.AllUsersAllHosts) } - 1 { writeDataToFile($PROFILE.CurrentUserAllHosts) } - 2 { writeDataToFile($PROFILE.CurrentUserCurrentHost) } - } - } +if ($PSVersionTable.PSVersion.Major -lt 5) { + writeErrorTip 'Sorry but PowerShell v5+ is required' + throw 'PowerShell''s version too low' +} +$temppath = ($env:TMP, $env:TEMP, '.' -ne $null)[0] +[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" - writeLogoLine ' _ ' - writeLogoLine ' __ ___ __ __ __ _| | ______ ' - writeLogoLine ' \ \/ / | \/ |/ _ | |/ / __ \ ' - writeLogoLine ' > < | \__/ | /_| | < ___/ ' - writeLogoLine ' /_/\_\_|_| |_|\__ \|_|\_\____| getter ' - writeLogoLine ' ' - writeLogoLine ' ' - - if ($PSVersionTable.PSVersion.Major -lt 5) { - writeErrorTip 'Sorry but PowerShell v5+ is required' - throw 'PowerShell''s version too low' - } - $temppath = ($env:TMP, $env:TEMP, '.' -ne $null)[0] - $outfile = $temppath + "\$pid-xmake-installer.exe" +function checkTempAccess { + $outfile = Join-Path $temppath "$pid.tmp" try { - Write-Output "$pid" | Out-File -FilePath "$outfile" - Remove-Item "$outfile" + Write-Output $pid | Out-File -FilePath $outfile + Remove-Item $outfile } catch { writeErrorTip 'Cannot write to temp path' writeErrorTip 'Please set environment var "TMP" to another path' - myExit 1 + throw } +} + +function xmakeInstall { + $outfile = Join-Path $temppath "$pid-xmake-installer.exe" Write-Host "Start downloading https://github.com/xmake-io/xmake/releases/download/$version/xmake-$branch.exe .." try { - [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" - Invoke-Webrequest "https://github.com/xmake-io/xmake/releases/download/$version/xmake-$branch.exe" -OutFile "$outfile" + Invoke-Webrequest "https://github.com/xmake-io/xmake/releases/download/$version/xmake-$branch.exe" -OutFile $outfile } catch { writeErrorTip 'Download failed!' writeErrorTip 'Check your network or... the news of S3 break' - myExit 1 + throw } Write-Host 'Start installation... Hope your antivirus doesn''t trouble' - $installdir = $HOME + '\xmake' Write-Host "Install to $installdir" try { - Start-Process -FilePath "$outfile" -ArgumentList "/S /D=$installdir" -Wait + Start-Process -FilePath $outfile -ArgumentList "/S /D=$installdir" -Wait } catch { - Remove-Item "$outfile" writeErrorTip 'Install failed!' writeErrorTip 'Close your antivirus then try again' - myExit 1 + throw + } finally { + Remove-Item $outfile -ErrorAction SilentlyContinue } - Remove-Item "$outfile" Write-Host 'Adding to PATH... almost done' $env:Path += ";$installdir" [Environment]::SetEnvironmentVariable("Path", [Environment]::GetEnvironmentVariable("Path", [System.EnvironmentVariableTarget]::User) + ";$installdir", [System.EnvironmentVariableTarget]::User) # this step is optional because installer writes path to regedit @@ -135,40 +80,117 @@ param ( } catch { writeErrorTip 'Everything is showing installation has finished' writeErrorTip 'But xmake could not run... Why?' - myExit 1 + throw } +} + +function xmakeSelfBuild { Write-Host "Pulling xmake from branch $branch" - $outfile = $temppath + "\$pid-xmake-repo.zip" + $outfile = Join-Path $temppath "$pid-xmake-repo.zip" try { - Invoke-Webrequest "https://github.com/xmake-io/xmake/archive/$branch.zip" -OutFile "$outfile" + Invoke-Webrequest "https://github.com/xmake-io/xmake/archive/$branch.zip" -OutFile $outfile } catch { writeErrorTip 'Pull Failed!' writeErrorTip 'xmake is now available but may not be newest' - myExit + throw } Write-Host 'Expanding archive...' - New-Item -Path "$temppath" -Name "$pid-xmake-repo" -ItemType "directory" -Force - $oldpwd = $pwd - $repodir = $temppath + "\$pid-xmake-repo" + $oldpwd = Get-Location + $repodir = New-Item -Path $temppath -Name "$pid-xmake-repo" -ItemType Directory -Force try { - Expand-Archive "$outfile" "$repodir" -Force + Expand-Archive -Path $outfile -DestinationPath $repodir -Force Write-Host 'Self-building...' - Set-Location ($repodir + "\xmake-$branch\core") + Set-Location $(Join-Path $repodir "\xmake-$branch\core") xmake Write-Host 'Copying new files...' - Copy-Item 'build\xmake.exe' "$installdir" -Force + Copy-Item -Path '.\build\xmake.exe' -Destination $installdir -Force Set-Location '..\xmake' - Copy-Item * "$installdir" -Recurse -Force + Copy-Item -Path * -Destination $installdir -Recurse -Force xmake --version } catch { writeErrorTip 'Update Failed!' writeErrorTip 'xmake is now available but may not be newest' + throw } finally { - Set-Location "$oldpwd" -ErrorAction SilentlyContinue - Remove-Item "$outfile" -ErrorAction SilentlyContinue - Remove-Item "$repodir" -Recurse -Force -ErrorAction SilentlyContinue + Set-Location $oldpwd -ErrorAction SilentlyContinue + Remove-Item $outfile -ErrorAction SilentlyContinue + Remove-Item $repodir -Recurse -Force -ErrorAction SilentlyContinue } +} - registerTabCompletion +function registerTabCompletion { + + function writeDataToFile($file) { + $encoding = [text.encoding]::UTF8 + if (Test-Path $file -PathType Leaf) { + #Create a stream reader to get the file's encoding and contents. + $sr = New-Object System.IO.StreamReader($file, $true) + [char[]] $buffer = new-object char[] 3 + $sr.Read($buffer, 0, 3) | Out-Null + $encoding = $sr.CurrentEncoding + $sr.Close() | Out-Null + + if ($(Get-Content $file) -imatch "Register-ArgumentCompleter -Native -CommandName xmake -ScriptBlock") { + Write-Host "Seems the tab completion of xmake has installed here..." + return + } + } + + try { + [IO.File]::AppendAllText($file, "`n", $encoding) + } catch { + writeErrorTip "Failed to append to profile!" + writeErrorTip "Please try again as administrator" + return + } + try { + $content = (Invoke-Webrequest 'https://raw.githubusercontent.com/xmake-io/xmake/master/scripts/register-completions.ps1' -UseBasicParsing).Content + } catch { + writeErrorTip 'Download failed!' + writeErrorTip 'Check your network or... the news of S3 break' + return + } + [IO.File]::AppendAllText($file, $content, $encoding) + [IO.File]::AppendAllText($file, "`n", $encoding) + } + $message = 'Tab completion service' + $question = 'Would you like to install tab completion service of xmake to your profile?' + + $choices = @( + (New-Object Management.Automation.Host.ChoiceDescription -ArgumentList @( + 'For &all users', + "Install for all users, writes to $($PROFILE.AllUsersAllHosts), admin privilege is needed.")), + (New-Object Management.Automation.Host.ChoiceDescription -ArgumentList @( + 'Just for &me', + "Install for current user, writes to $($PROFILE.CurrentUserAllHosts).")), + (New-Object Management.Automation.Host.ChoiceDescription -ArgumentList @( + 'Just for this &host', + "Install for current user current host, writes to $($PROFILE.CurrentUserCurrentHost).")), + (New-Object Management.Automation.Host.ChoiceDescription -ArgumentList @( + '&No', + "Do not install xmake's tab completion service.")) + ) + switch ($Host.UI.PromptForChoice($message, $question, $choices, 1)) { + 0 { writeDataToFile($PROFILE.AllUsersAllHosts) } + 1 { writeDataToFile($PROFILE.CurrentUserAllHosts) } + 2 { writeDataToFile($PROFILE.CurrentUserCurrentHost) } + } +} +try { + checkTempAccess + xmakeInstall +} catch { + myExit 1 } + + +if (-not $env:CI) { + try { + xmakeSelfBuild + } catch { } # continue + registerTabCompletion +} else { + Write-Host "Self bulid and tab completion registration has been skipped for CI" +} + diff --git a/tests/modules/devel/git/test.lua b/tests/modules/devel/git/test.lua new file mode 100644 index 00000000000..ddcfc94b248 --- /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 00000000000..2c45b6ae157 --- /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 108468a2194..cab44adf335 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,21 +63,22 @@ 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 -- confirm to install? - local confirm = utils.confirm({default = true, description = "try continue to run `%s` with administrator permission again"}) + local confirm = utils.confirm({ default = true, description = format("try continue to run `%s` with administrator permission again", command) }) 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 download 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 5e42a943678..ae7f1a58f73 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 00000000000..2b8f5ea7ed2 --- /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 00000000000..24fa86c4aa0 --- /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 [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 9bc71637c4e..00000000000 --- 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 [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 00000000000..760db081715 --- /dev/null +++ b/xmake/scripts/update-script.bat @@ -0,0 +1,7 @@ +@echo off + +echo Removing old files +cd /d "%~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 00000000000..e135a31b35f --- /dev/null +++ b/xmake/scripts/update-script.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +cd "$1" +rm -rf actions core includes languages modules platforms plugins repository rules scripts templates themes +cp -rf "$2" "$1/.." \ No newline at end of file