├── ..sln ├── .gitattributes ├── .github └── FUNDING.yml ├── .gitignore ├── .tools ├── hMSBuild.bat └── packages.config ├── .version ├── .vssbe ├── License.txt ├── Readme.md ├── build.bat ├── caller.bat ├── changelog.txt ├── csharp.cs ├── csinit.targets ├── demo.vssbe.bat ├── demo └── vsSolutionBuildEvent.bat ├── embd.bat ├── tests.bat ├── tests ├── _run.bat ├── a.bat └── keysAndLogicTests.bat └── vsSolutionBuildEvent.bat /..sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.8.34408.163 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GetNuTool", "GetNuTool", "{D221D332-2A57-44F9-B866-F7C00C29032D}" 7 | ProjectSection(SolutionItems) = preProject 8 | .version = .version 9 | build.bat = build.bat 10 | caller.bat = caller.bat 11 | changelog.txt = changelog.txt 12 | embd.bat = embd.bat 13 | logic.cs = logic.cs 14 | logic.targets = logic.targets 15 | tests.bat = tests.bat 16 | vsSolutionBuildEvent.bat = vsSolutionBuildEvent.bat 17 | EndProjectSection 18 | EndProject 19 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{FFA2896B-A6DF-43DB-AB4B-8D3C7AB234C3}" 20 | ProjectSection(SolutionItems) = preProject 21 | tests\a.bat = tests\a.bat 22 | tests\keysAndLogicTests.bat = tests\keysAndLogicTests.bat 23 | tests\_run.bat = tests\_run.bat 24 | EndProjectSection 25 | EndProject 26 | Global 27 | GlobalSection(SolutionProperties) = preSolution 28 | HideSolutionNode = FALSE 29 | EndGlobalSection 30 | GlobalSection(NestedProjects) = preSolution 31 | {FFA2896B-A6DF-43DB-AB4B-8D3C7AB234C3} = {D221D332-2A57-44F9-B866-F7C00C29032D} 32 | EndGlobalSection 33 | GlobalSection(ExtensibilityGlobals) = postSolution 34 | SolutionGuid = {FFF98BCF-06C1-4BF8-88DF-5F04681BC6AB} 35 | EndGlobalSection 36 | EndGlobal 37 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | 2 | # Batch files requires CRLF https://github.com/3F/hMSBuild/issues/2 3 | 4 | *.bat text eol=crlf 5 | *.cmd text eol=crlf 6 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # ____ 2 | # /___/|\ 3 | # `~|___| ! With open love to open source. 4 | # /___/ \; Yours, github.com/3F 5 | # 6 | 7 | custom: ['3F.github.io/fund'] 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | obj 3 | *.suo 4 | .vs 5 | .vssbe.user 6 | /packages 7 | *.nupkg 8 | /tests/packages 9 | /tests/T00LS 10 | /demo/wrappers/packages 11 | /demo/packages 12 | /demo/*.sln 13 | -------------------------------------------------------------------------------- /.tools/hMSBuild.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | :: hMSBuild 2.4.1.54329+caba551 3 | :: Copyright (c) 2017-2024 Denis Kuzmin github/3F 4 | :: Copyright (c) hMSBuild contributors https://github.com/3F/hMSBuild 5 | set "hh=%~dp0"&set hi=%*&if not defined hi setlocal enableDelayedExpansion & goto i0 6 | if not defined __p_call set hi=%hi:^=^^% 7 | set hj=%hi:!= L % 8 | set hj=%hj:^= T % 9 | setlocal enableDelayedExpansion&set "hk=^"&set "hj=!hj:%%=%%%%!"&set "hj=!hj:&=%%hk%%&!" 10 | :i0 11 | set "hl=2.8.4"&set hm=%temp%\hMSBuild_vswhere&set "hn="&set "ho="&set "hp="&set "hq="&set "hr="&set "hs="&set "ht="&set "hu="&set "hv="&set "hw="&set "hx="&set "hy="&set "hz="&set "ha="&set "hb="&set /a hc=0&if not defined hi goto i1 12 | set hj=!hj:/?=/h!&call :i2 ic hj id&goto i3 13 | :i4 14 | echo.&echo hMSBuild 2.4.1.54329+caba551&echo Copyright (c) 2017-2024 Denis Kuzmin ^ github/3F&echo Copyright (c) hMSBuild contributors https://github.com/3F/hMSBuild&echo.&echo Under the MIT License https://github.com/3F/hMSBuild&echo.&echo Syntax: %~n0 [keys to %~n0] [keys to MSBuild.exe or GetNuTool]&echo.&echo Keys&echo ~~~~&echo -no-vs - Disable searching from Visual Studio.&echo -no-netfx - Disable searching from .NET Framework.&echo -no-vswhere - Do not search via vswhere.&echo -no-less-15 - Do not include versions less than 15.0 (install-API/2017+)&echo -no-less-4 - Do not include versions less than 4.0 (Windows XP+)&echo.&echo -priority {IDs} - 15+ Non-strict components preference: C++ etc.&echo Separated by space "a b c" https://aka.ms/vs/workloads&echo.&echo -vswhere {v}&echo * 2.6.7 ...&echo * latest - To get latest remote vswhere.exe&echo * local - To use only local&echo (.bat;.exe /or from +15.2.26418.1 VS-build)&echo.&echo -no-cache - Do not cache vswhere for this request.&echo -reset-cache - To reset all cached vswhere versions before processing.&echo -cs - Adds to -priority C# / VB Roslyn compilers.&echo -vc - Adds to -priority VC++ toolset.&echo ~c {name} - Alias to p:Configuration={name}&echo ~p {name} - Alias to p:Platform={name}&echo ~x - Alias to m:NUMBER_OF_PROCESSORS-1 v:m&echo -notamd64 - To use 32bit version of found msbuild.exe if it's possible.&echo -stable - It will ignore possible beta releases in last attempts.&echo -eng - Try to use english language for all build messages. 15 | echo -GetNuTool {args} - Access to GetNuTool core. https://github.com/3F/GetNuTool&echo -only-path - Only display fullpath to found MSBuild.&echo -force - Aggressive behavior for -priority, -notamd64, etc.&echo -vsw-as "args..." - Reassign default commands to vswhere if used.&echo -debug - To show additional information from %~n0&echo -version - Display version of %~n0.&echo -help - Display this help. Aliases: -? -h&echo.&echo.&echo MSBuild switches&echo ~~~~~~~~~~~~~~~~&echo /help or /? or /h&echo Use /... if %~n0 overrides some -... MSBuild switches&echo.&echo.&echo Try to execute:&echo %~n0 -only-path -no-vs -notamd64 -no-less-4&echo %~n0 -debug ~x ~c Release&echo %~n0 -GetNuTool "Conari;regXwild;Fnv1a128"&echo %~n0 -GetNuTool vsSolutionBuildEvent/1.16.0:../SDK ^& SDK\GUI 16 | echo %~n0 -cs -no-less-15 /t:Rebuild&goto i5 17 | :i3 18 | set "hd="&set /a he=0 19 | :i6 20 | set hf=!ic[%he%]!&(if [!hf!]==[-help] (goto i4)else if [!hf!]==[-h] (goto i4)else if [!hf!]==[-?] (goto i4 ))&(if [!hf!]==[-nocachevswhere] (call :i7 -nocachevswhere -no-cache -reset-cache 21 | set hf=-no-cache)else if [!hf!]==[-novswhere] (call :i7 -novswhere -no-vswhere&set hf=-no-vswhere)else if [!hf!]==[-novs] (call :i7 -novs -no-vs&set hf=-no-vs)else if [!hf!]==[-nonet] (call :i7 -nonet -no-netfx&set hf=-no-netfx)else if [!hf!]==[-vswhere-version] (call :i7 -vswhere-version -vswhere&set hf=-vswhere)else if [!hf!]==[-vsw-version] (call :i7 -vsw-version -vswhere&set hf=-vswhere)else if [!hf!]==[-vsw-priority] (call :i7 -vsw-priority -priority&set hf=-priority))&(if [!hf!]==[-debug] (set ht=1 22 | goto i8)else if [!hf!]==[-GetNuTool] (call :i9 "accessing to GetNuTool ..."&(for /L %%p in (0,1,8181)do (if "!hj:~%%p,10!"=="-GetNuTool" (set hg=!hj:~%%p! 23 | call :jh !hg:~10!&set /a hc=!ERRORLEVEL!&goto i5)))&call :i9 "!hf! is corrupted: " hj&set /a hc=1&goto i5)else if [!hf!]==[-no-vswhere] (set hq=1&goto i8)else if [!hf!]==[-no-cache] (set hr=1&goto i8)else if [!hf!]==[-reset-cache] (set hs=1&goto i8)else if [!hf!]==[-no-vs] (set ho=1&goto i8)else if [!hf!]==[-no-less-15] (set ha=1&set hp=1&goto i8)else if [!hf!]==[-no-less-4] (set hb=1&goto i8)else if [!hf!]==[-no-netfx] (set hp=1&goto i8)else if [!hf!]==[-notamd64] (set hn=1&goto i8)else if [!hf!]==[-only-path] (set hu=1&goto i8)else if [!hf!]==[-eng] (chcp 437 >nul&goto i8)else if [!hf!]==[-vswhere] (set /a "he+=1" & call :ji ic[!he!] v 24 | set hl=!v!&call :i9 "selected vswhere version:" v&set hv=1&goto i8)else if [!hf!]==[-version] (echo 2.4.1.54329+caba551&goto i5)else if [!hf!]==[-priority] (set /a "he+=1" & call :ji ic[!he!] v 25 | set hw=!v! !hw!&goto i8)else if [!hf!]==[-vsw-as] (set /a "he+=1" & call :ji ic[!he!] v 26 | set hx=!v!&goto i8)else if [!hf!]==[-cs] (set hw=Microsoft.VisualStudio.Component.Roslyn.Compiler !hw!&goto i8)else if [!hf!]==[-vc] (set hw=Microsoft.VisualStudio.Component.VC.Tools.x86.x64 !hw!&goto i8)else if [!hf!]==[~c] (set /a "he+=1" & call :ji ic[!he!] v 27 | set hd=!hd! /p:Configuration="!v!"&goto i8)else if [!hf!]==[~p] (set /a "he+=1" & call :ji ic[!he!] v 28 | set hd=!hd! /p:Platform="!v!"&goto i8)else if [!hf!]==[~x] (set /a h0=NUMBER_OF_PROCESSORS - 1&set hd=!hd! /v:m /m:!h0!&goto i8)else if [!hf!]==[-stable] (set hy=1&goto i8)else if [!hf!]==[-force] (set hz=1&goto i8)else (call :i9 "non-handled key: " ic{%he%}&set hd=!hd! !ic{%he%}!)) 29 | :i8 30 | set /a "he+=1" & if %he% LSS !id! goto i6 31 | :i1 32 | (if defined hs (call :i9 "resetting vswhere cache" 33 | rmdir /S/Q "%hm%" 2>nul))&(if not defined hq if not defined ho (call :jj ie 34 | if defined ie goto jk))&(if not defined ho if not defined ha (call :jl ie 35 | if defined ie goto jk))&(if not defined hp (call :jm ie 36 | if defined ie goto jk)) 37 | echo MSBuild tools was not found. Use `-debug` key for details.>&2 38 | set /a hc=2&goto i5 39 | :jk 40 | (if defined hu (echo !ie! 41 | goto i5))&set h1="!ie!"&echo hMSBuild: !h1!&if not defined hd goto jn 42 | set hd=%hd: T =^% 43 | set hd=%hd: L =^!% 44 | set hd=!hd: E ==! 45 | :jn 46 | call :i9 "Arguments: " hd&!h1! !hd! 47 | set /a hc=%ERRORLEVEL%&goto i5 48 | :i5 49 | exit/B!hc! 50 | :jj 51 | call :i9 "try vswhere..."&(if defined hv if not "!hl!"=="local" (call :jo h8 h2 52 | call :jp h8 if h2&set %1=!if!&exit/B0))&call :jq h8&set "h2="&(if not defined h8 ((if "!hl!"=="local" (set "%1=" & exit/B2)) 53 | call :jo h8 h2))&call :jp h8 if h2&set %1=!if!&exit/B0 54 | :jq 55 | set h3=!hh!vswhere&call :jr h3 ig&if defined ig set "%1=!h3!" & exit/B0 56 | set h4=Microsoft Visual Studio\Installer&if exist "%ProgramFiles(x86)%\!h4!" set "%1=%ProgramFiles(x86)%\!h4!\vswhere" & exit/B0 57 | if exist "%ProgramFiles%\!h4!" set "%1=%ProgramFiles%\!h4!\vswhere" & exit/B0 58 | call :i9 "local vswhere is not found."&set "%1="&exit/B3 59 | :jo 60 | (if defined hr (set h5=!hm!\_mta\%random%%random%vswhere)else (set h5=!hm! 61 | (if defined hl (set h5=!h5!\!hl!)))) 62 | call :i9 "tvswhere: " h5&(if "!hl!"=="latest" (set h6=vswhere)else (set h6=vswhere/!hl!)) 63 | set h7=/p:ngpackages="!h6!:vswhere" /p:ngpath="!h5!"&call :i9 "GetNuTool call: " h7&setlocal&set __p_call=1&(if defined ht (call :jh !h7!)else (call :jh !h7! >nul)) 64 | endlocal&set "%1=!h5!\vswhere\tools\vswhere"&set "%2=!h5!"&exit/B0 65 | :jp 66 | set "h8=!%1!"&set "h9=!%3!"&call :jr h8 h8&(if not defined h8 (call :i9 "vswhere tool does not exist" 67 | set "%2=" & exit/B1)) 68 | call :i9 "vswbin: " h8&set "ih="&set "ii="&set ij=!hw!&if not defined hx set hx=-products * -latest 69 | call :i9 "assign command: `!hx!`" 70 | :js 71 | call :i9 "attempts with filter: !ij!; `!ih!`"&set "ik=" & set "il=" 72 | (for /F "usebackq tokens=1* delims=: " %%a in (`"!h8!" -nologo !ih! -requires !ij! Microsoft.Component.MSBuild !hx!`) do (if /I "%%~a"=="installationPath" set ik=%%~b 73 | if /I "%%~a"=="installationVersion" set il=%%~b 74 | (if defined ik if defined il (call :jt ik il ii 75 | if defined ii goto ju 76 | set "ik=" & set "il="))))&(if not defined hy if not defined ih (set ih=-prerelease 77 | goto js))&(if defined ij (set im=Tools was not found for: !ij! 78 | (if defined hz (call :i9 "Ignored via -force. !im!" 79 | set "ii=" & goto ju)) 80 | call :jv "!im!"&set "ij=" & set "ih=" 81 | goto js)) 82 | :ju 83 | (if defined h9 if defined hr (call :i9 "reset vswhere " h9 84 | rmdir /S/Q "!h9!"))&set %2=!ii!&exit/B0 85 | :jt 86 | set ik=!%1!&set il=!%2!&call :i9 "vspath: " ik&call :i9 "vsver: " il&(if not defined il (call :i9 "nothing to see via vswhere" 87 | set "%3=" & exit/B3)) 88 | (for /F "tokens=1,2 delims=." %%a in ("!il!") do (set il=%%~a.0))&if !il! geq 16 set il=Current 89 | if not exist "!ik!\MSBuild\!il!\Bin" set "%3=" & exit/B3 90 | set in=!ik!\MSBuild\!il!\Bin&call :i9 "found path via vswhere: " in&(if exist "!in!\amd64" (call :i9 "found /amd64" 91 | set in=!in!\amd64))&call :jw in in&set %3=!in!&exit/B0 92 | :jl 93 | call :i9 "Searching from Visual Studio - 2015, 2013, ..."&(for %%v in (14.0,12.0)do (call :jx %%v Y & (if defined Y (set %1=!Y! 94 | exit/B0))))&call :i9 "-vs: not found"&set "%1="&exit/B0 95 | :jm 96 | call :i9 "Searching from .NET Framework - .NET 4.0, ..."&(for %%v in (4.0,3.5,2.0)do (call :jx %%v Y & (if defined Y (set %1=!Y! 97 | exit/B0)else if defined hb (goto :jy )))) 98 | :jy 99 | call :i9 "-netfx: not found"&set "%1="&exit/B0 100 | :jx 101 | call :i9 "check %1"&(for /F "usebackq tokens=2* skip=2" %%a in (`reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\%1" /v MSBuildToolsPath 2^> nul`) do (if exist %%b (set in=%%~b 102 | call :i9 ":msbfound " in&call :jw in if&set %2=!if!&exit/B0)))&set "%2="&exit/B0 103 | :jw 104 | set in=!%~1!\MSBuild.exe&if exist "!in!" set "%2=!in!" 105 | (if not defined hn (exit/B0)) 106 | set io=!in:Framework64=Framework!&set io=!io:\amd64=!&(if exist "!io!" (call :i9 "Return 32bit version because of -notamd64 key." 107 | set %2=!io!&exit/B0))&(if defined hz (call :i9 "Ignored via -force. Only 64bit version was found for -notamd64" 108 | set "%2=" & exit/B0)) 109 | if not "%2"=="" call :jv "Return 64bit version. Found only this." 110 | exit/B0 111 | :jr 112 | call :i9 "bat/exe: " %1&if exist "!%1!.bat" set %2="!%1!.bat" & exit/B0 113 | if exist "!%1!.exe" set %2="!%1!.exe" & exit/B0 114 | set "%2="&exit/B0 115 | :i7 116 | call :jv "'%~1' is obsolete. Use: %~2 %~3"&exit/B0 117 | :jv 118 | echo [*] WARN: %~1 >&2 119 | exit/B0 120 | :i9 121 | (if defined ht (set "ip=%~1" & echo [ %TIME% ] !ip! !%2! !%3!)) 122 | exit/B0 123 | :i2 124 | set iq=!%2! 125 | :jz 126 | (for /F "tokens=1* delims==" %%a in ("!iq!") do (if "%%~b"=="" (call :ja %1 !iq! %3 & exit/B0)else set iq=%%a E %%b))&goto jz 127 | :ja 128 | set "ir=%~1"&set /a he=-1 129 | :jb 130 | set /a he+=1&set %ir%[!he!]=%~2&set %ir%{!he!}=%2&if "%~4" NEQ "" shift & goto jb 131 | set %3=!he!&exit/B0 132 | :ji 133 | set is=!%1! 134 | set "is=%is: T =^%" 135 | set "is=%is: L =^!%" 136 | set is=!is: E ==! 137 | set %2=!is!&exit/B0 138 | :jh 139 | setlocal disableDelayedExpansion&@echo off 140 | :: GetNuTool /shell/batch edition 141 | :: Copyright (c) 2015-2024 Denis Kuzmin github/3F 142 | :: https://github.com/3F/GetNuTool 143 | set it=gnt.core&set iu="%temp%\%it%1.9.0%random%%random%"&if "%~1"=="-unpack" goto jc 144 | if "%~1"=="-msbuild" goto jd 145 | set iv=%*&setlocal enableDelayedExpansion&set "iw=%~1 "&set ix=!iw:~0,1!&if "!ix!" NEQ " " if !ix! NEQ / set iv=/p:ngpackages=!iv! 146 | set "iy=%msb.gnt.cmd%"&if defined iy goto je 147 | set iz=hMSBuild&if exist msb.gnt.cmd set iz=msb.gnt.cmd 148 | for /F "tokens=*" %%i in ('%iz% -only-path 2^>^&1 ^&call echo %%^^ERRORLEVEL%%') do 2>nul (if not defined iy (set iy="%%i")else set ia=%%i) 149 | if .%ia%==.0 if exist !iy! goto je 150 | (for %%v in (4.0,14.0,12.0,3.5,2.0)do (for /F "usebackq tokens=2* skip=2" %%a in (`reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\%%v" /v MSBuildToolsPath 2^> nul`) do (if exist %%b (set iy="%%~b\MSBuild.exe" 151 | (if exist !iy! (if %%v NEQ 3.5 if %%v NEQ 2.0 goto je 152 | echo Override engine or contact for legacy support %%v&exit/B120))))))&echo Engine is not found. Try with hMSBuild 1>&2 153 | exit/B2 154 | :jd 155 | echo This feature is disabled in current version >&2 156 | exit/B120 157 | :je 158 | set ib=/noconlog&if "%debug%"=="true" set ib=/v:q 159 | call :jf&call :jg "/help" "-help" "/h" "-h" "/?" "-?"&call !iy! %iu% /nologo /noautorsp !ib! /p:wpath="%cd%/" !iv!&set ia=!ERRORLEVEL!&del /Q/F %iu%&exit/B!ia! 160 | :jc 161 | set iu="%cd%\%it%"&echo Generating a %it% at %cd%\... 162 | :jf 163 | setlocal disableDelayedExpansion 164 | %iu%&set -=ngconfig&set [=Condition&set ]=packages.config&set ;=ngserver&set .=package&set ,=GetNuTool&set :=wpath&set +=TaskCoreDllPath&set {=Exists&set }=MSBuildToolsPath&set _=Microsoft.Build.Tasks.&set a=MSBuildToolsVersion&set b=Target&set c=tmode&set d=ParameterGroup&set e=Reference&set f=System&set g=Namespace&set h=Console.WriteLine(&set i=string&set j=return&set k=Console.Error.WriteLine(&set l=string.IsNullOrEmpty(&set m=foreach&set n=Attribute&set o=Append&set p=Path&set q=Combine&set r=Length&set s=false&set t=ToString&set u=SecurityProtocolType&set v=ServicePointManager.SecurityProtocol&set w=Credentials&set x=Directory&set y=CreateDirectory&set z=Console.Write(&set $=using&set #=FileMode&set @=FileAccess&set `=StringComparison&set ?=StartsWith 165 | ^^^<%-% %[%="'$(%-%)'==''"^>%]%;.tools\%]%^^<%;% %[%="'$(%;%)'==''"^>https://www.nuget.org/api/v2/%.%/^^packages^^<%,%^>1.9.0.1956+bb83b59^^<%:% %[%="'$(%:%)'==''"^>$(MSBuildProjectDirectory)^^<%+% %[%="%{%('$(%}%)\%_%v$(%a%).dll')"^>$(%}%)\%_%v$(%a%).dll^^<%+% %[%="'$(%+%)'=='' and %{%('$(%}%)\%_%Core.dll')"^>$(%}%)\%_%Core.dll^^^<%b% Name="get" BeforeTargets="Build"^>^^^<%b% Name="grab"^>^^^<%b% Name="pack"^>^^^^<%d%^>^<%c%/^>^^^<%e% Include="%f%.Xml"/^>^<%e% Include="%f%.Xml.Linq"/^>^<%e% Include="WindowsBase"/^>^^^^^^^^ github/3F\n");var d="{0} is not found ";var e=new %i%[]{"/_rels/","/%.%/","/[Content_Types].xml"};Action^<%i%,object^>f=(g,h)=^>{if("$(debug)".Trim()=="true")%h%g,h);};Func^<%i%,XElement^>i=j=^>{try{%j% XDocument.Load(j).Root;}catch(Exception k){%k%k.Message);throw;}};Func^<%i%,%i%[]^>l=m=^>m.Split(new[]{m.Contains('^|')?'^|':';'},(StringSplitOptions)1);if(%c%=="get"^|^|%c%=="grab"){var n=@"$(ngpackages)";var o=new StringBuilder();if(%l%n)){Action^<%i%^>p=q=^>{%m%(var r in i(q).Descendants("%.%")){var s=r.%n%("id");var t=r.%n%("version");var u=r.%n%("output");var v=r.%n%("sha1");if(s==null){%k%"{0} is corrupted",q);%j%;}o.%o%(s.Value);if(t!=null)o.%o%("/"+t.Value);if(v!=null)o.%o%("?"+v.Value);if(u!=null)o.%o%(":">>%iu% 166 | ()){try{%v%^|=z;}catch(NotSupportedException){}}if("$(ssl3)"!="true")%v%^&=~(%u%)(48^|192^|768);Func^<%i%,WebProxy^>D=q=^>{var E=q.Split('@');if(E.%r%^<=1)%j% new WebProxy(E[0],%s%);var F=E[0].Split(':');%j% new WebProxy(E[1],%s%){%w%=new NetworkCredential(F[0],F.%r%^>1?F[1]:null)};};Func^<%i%,%i%^>G=H=^>{var I=%p%.GetDirectoryName(H);if(!%x%.%{%(I))%x%.%y%(I);%j% H;};Func^<%i%,%i%,%i%,%i%,bool^>J=(K,L,H,v)=^>{var M=%p%.GetFullPath(%p%.%q%(@"$(%:%)",H??L??""));if(%x%.%{%(M)^|^|File.%{%(M)){%h%"{0} use {1}",L,M);%j% true;}%z%K+" ... ");var N=%c%=="grab";var O=N?G(M):%p%.%q%(%p%.GetTempPath(),Guid.NewGuid().%t%());%$%(var P=new WebClient()){try{if(!%l%y)){P.Proxy=D(y);}P.Headers.Add("User-Agent","%,%/$(%,%)");P.UseDefaultCredentials=true;if(P.Proxy!=null^&^&P.Proxy.%w%==null){P.Proxy.%w%=CredentialCache.DefaultCredentials;}P.DownloadFile(@"$(%;%)"+K,O);}catch(Exception k){%k%k.Message);%j% %s%;}}%h%M);if(v!=null){%z%"{0} ... ",v);%$%(var Q=%f%.Security.Cryptography.SHA1.Create()){o.Clear();%$%(var R=new FileStream(O,(%#%)3,(%@%)1))%m%(var S in Q.ComputeHash(R))o.%o%(S.%t%("x2"));%z%o.%t%());if(!o.%t%().Equals(v,(%`%)5)){%h%"[x]");%j% %s%;}%h%);}}if(N)%j% true;%$%(var r=ZipPackage.Open(O,(%#%)3,(%@%)1)){%m%(var T in r.GetParts()){var U=Uri.UnescapeDataString(T.Uri.OriginalString);if(e.Any(V=^>U.%?%(V,(%`%)4)))continue;var W=%p%.%q%(M,U.TrimStart('/'));f("- {0}",U);%$%(var X=T.GetStream((%#%)3,(%@%)1))%$%(var Y=File.OpenWrite(G(W))){try{X.CopyTo(Y);}catch(FileFormatException){f("[x]?crc: {0}",W);}}}}File.Delete(O);%j% true;};%m%(var r in l(n)){var Z=r.Split(new[]{':'},2);var K=Z[0].Split(new[]{'?'},2);var H=Z.%r%^>1?Z[1]:null;var L=K[0].Replace(>>%iu% 167 | 1?K[1]:null)^&^&"$(break)".Trim()!="no")%j% %s%;}}else if(%c%=="pack"){var a=".nuspec";var b="metadata";var c="id";var A="version";var I=%p%.%q%(@"$(%:%)",@"$(ngin)");if(!%x%.%{%(I)){%k%d,I);%j% %s%;}var B=%x%.GetFiles(I,"*"+a).FirstOrDefault();if(B==null){%k%d+I,a);%j% %s%;}%h%"{0} use {1}",a,B);var C=i(B).Elements().FirstOrDefault(V=^>V.Name.LocalName==b);if(C==null){%k%d,b);%j% %s%;}var _=new %f%.Collections.Generic.Dictionary^<%i%,%i%^>();Func^<%i%,%i%^>dd=de=^>_.ContainsKey(de)?_[de]:"";%m%(var df in C.Elements())_[df.Name.LocalName.ToLower()]=df.Value;if(dd(c).%r%^>100^|^|!%f%.Text.RegularExpressions.Regex.IsMatch(dd(c),@"^\w+(?:[_.-]\w+)*$")){%k%"Invalid id");%j% %s%;}var dg=%i%.Format("{0}.{1}.nupkg",dd(c),dd(A));var dh=%p%.%q%(@"$(%:%)",@"$(ngout)");if(!%i%.IsNullOrWhiteSpace(dh)){if(!%x%.%{%(dh)){%x%.%y%(dh);}dg=%p%.%q%(dh,dg);}%h%"Creating %.% {0} ...",dg);%$%(var r=Package.Open(dg,(%#%)2)){var di=new Uri(%i%.Format("/{0}{1}",dd(c),a),(UriKind)2);r.CreateRelationship(di,0,"http://schemas.microsoft.com/packaging/2010/07/manifest");%m%(var dj in %x%.GetFiles(I,"*.*",(SearchOption)1)){if(e.Any(V=^>dj.%?%(%p%.%q%(I,V.Trim('/')),(%`%)4)))continue;var dk=dj.%?%(I,(%`%)5)?dj.Substring(I.%r%).TrimStart(%p%.DirectorySeparatorChar):dj;f("+ {0}",dk);var T=r.CreatePart(PackUriHelper.CreatePartUri(new Uri(%i%.Join("/",dk.Split('\\','/').Select(Uri.EscapeDataString)),(UriKind)2)),"application/octet",(CompressionOption)1);%$%(var dl=T.GetStream())%$%(var dm=new FileStream(dj,(%#%)3,(%@%)1)){dm.CopyTo(dl);}}var dn=r.PackageProperties;dn.Creator=dd("authors");dn.Description=dd("description");dn.Identifier=dd(c);dn.Version=dd(A);dn.Keywords=dd("tags");dn.Title=dd("title");dn.LastModifiedBy="%,%/$(%,%)";}}else %j% %s%;]]^>^^^^<%b% Name="Build" DependsOnTargets="%,%"/^>^>>%iu% 168 | endlocal&exit/B0 169 | :jg 170 | if defined iv set iv=!iv:%~1=! 171 | if "%~2" NEQ "" shift & goto jg 172 | exit/B0 -------------------------------------------------------------------------------- /.tools/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /.version: -------------------------------------------------------------------------------- 1 | 1.9.0 -------------------------------------------------------------------------------- /.vssbe: -------------------------------------------------------------------------------- 1 | { 2 | "Header": { 3 | "_": [ 4 | " This file for vsSolutionBuildEvent ", 5 | " https://github.com/3F/vsSolutionBuildEvent " 6 | ], 7 | "Compatibility": "0.12.4" 8 | }, 9 | "PreBuild": [ 10 | { 11 | "Enabled": true, 12 | "Name": "Prepare", 13 | "Caption": "Prepare data and directories", 14 | "Mode": { 15 | "$type": "net.r_eg.vsSBE.Events.ModeScript, vsSolutionBuildEvent", 16 | "Type": "Script", 17 | "Command__": [ 18 | "#[$(dbin = \"bin/Release/\")]", 19 | "#[$(dobj = \"obj/\")]", 20 | "", 21 | "~ Inputs", 22 | "", 23 | "$(fCore = '$(dobj)core')", 24 | "$(fCoreMin = '$(dobj)gnt.min.core')", 25 | "$(fPacked = '$(dobj)gnt.bat')", 26 | "$(fEmbd = 'embd.bat')", 27 | "$(fPackMin = '$(dobj)gnt.minified.bat')", 28 | "", 29 | "#[($(packmaxline) == *Undefined*){ $(packmaxline = '1900') }]", 30 | "", 31 | "~ Output structure", 32 | "", 33 | "$(odir = \"$(dbin)raw/\")", 34 | "", 35 | "#[IO delete.directory(\"$(dbin)\", true)]", 36 | "#[IO copy.directory(\"\", \"$(dbin)\", true)]", 37 | "#[IO copy.directory(\"\", \"$(dobj)\", true)]" 38 | ] 39 | } 40 | }, 41 | { 42 | "Enabled": true, 43 | "Name": "ActCs", 44 | "SupportMSBuild": false, 45 | "Mode": { 46 | "$type": "net.r_eg.vsSBE.Events.ModeScript, vsSolutionBuildEvent", 47 | "Type": "Script", 48 | "Command__": [ 49 | "", 50 | "initialize without msbuild processing", 51 | "#[var cslogic = #[IO get(\"csharp.cs\")]]" 52 | ] 53 | } 54 | }, 55 | { 56 | "Enabled": true, 57 | "Name": "ActCore", 58 | "Mode": { 59 | "$type": "net.r_eg.vsSBE.Events.ModeScript, vsSolutionBuildEvent", 60 | "Type": "Script", 61 | "Command__": [ 62 | "#[$(revDeltaBase = \"2017/08/12\")]", 63 | "#[$(revDeltaMin = $([System.Math]::Pow(10, 3)))]", 64 | "#[$(revDeltaMax = 65534)]", 65 | "", 66 | "#[var pVer = #[File get(\".version\")]]", 67 | "", 68 | "#[\" ", 69 | " Calculate revision", 70 | "\"]", 71 | "#[var tBase = $([System.DateTime]::Parse('$(revDeltaBase)').ToBinary())]", 72 | "#[var tNow = $([System.DateTime]::UtcNow.Ticks)]", 73 | "#[var revBuild = #[$(", 74 | " [System.TimeSpan]::FromTicks('$(", 75 | " [MSBuild]::Subtract($(tNow), $(tBase))", 76 | " )')", 77 | " .TotalMinutes.ToString('0'))]]", 78 | " ", 79 | "#[var revBuild = #[$(", 80 | " [MSBuild]::Add(", 81 | " $(revDeltaMin), ", 82 | " $([MSBuild]::Modulo(", 83 | " $(revBuild), ", 84 | " $([MSBuild]::Subtract(", 85 | " $(revDeltaMax), $(revDeltaMin)", 86 | " ))", 87 | " ))", 88 | " )", 89 | " )]", 90 | "]", 91 | "", 92 | "#[$(pVerPrintFile = \"$(pVer).$(revBuild)\"))]", 93 | "", 94 | "#[\" ", 95 | " Checking of the git folder +tool & define sha1, branch name, etc.", 96 | "\"]", 97 | "#[var isGit = #[IO cmd(\"git rev-parse 2>&1\")]]", 98 | "#[( $(isGit) == \"\" )", 99 | "{", 100 | " #[var bSha1 = #[IO sout(\"git\", \"rev-parse --short HEAD\")]]", 101 | " ", 102 | " #[$(pVerPrintFile = \"$(pVerPrintFile)+$(bSha1)\")]", 103 | "}", 104 | "else {", 105 | " #[$(bSha1 = '-')]", 106 | "}]", 107 | "", 108 | "#[( $(reltype) == \"PublicRelease\" ) {", 109 | " #[$(pVerPrintApp = \"$(pVer).$(revBuild)+$(bSha1)\")]", 110 | "}", 111 | "else {", 112 | " #[$(pVerPrintApp = $(pVer))]", 113 | "}]", 114 | "", 115 | "#[\" obj \"]", 116 | "", 117 | "#[IO copy.file(\"csinit.targets\", \"$(dobj)core\", true)]", 118 | "#[IO replace.Regex(\"$(dobj)core\", \".*?\", \"$(pVerPrintApp)\")]", 119 | "", 120 | "$ -> $$ to prevent double evaluation", 121 | "#[IO replace", 122 | "(", 123 | " \"$(dobj)core\",", 124 | " \"return true;\",", 125 | " \"$(cslogic.Replace('$(', '$$('))\"", 126 | ")]" 127 | ] 128 | } 129 | }, 130 | { 131 | "Enabled": true, 132 | "Name": "CompressorMinified", 133 | "Caption": ".compressor at /minified ", 134 | "SupportSBEScripts": false, 135 | "Mode": { 136 | "$type": "net.r_eg.vsSBE.Events.ModeCSharp, vsSolutionBuildEvent", 137 | "Type": "CSharp", 138 | "References": [ 139 | "System.dll", 140 | "System.Core.dll" 141 | ], 142 | "SmartReferences": true, 143 | "GenerateInMemory": true, 144 | "TreatWarningsAsErrors": false, 145 | "WarningLevel": 4, 146 | "FilesMode": false, 147 | "CachingBytecode": false, 148 | "Command__": [ 149 | "/*", 150 | "* Copyright (c) 2015 Denis Kuzmin github/3F", 151 | "*", 152 | "* Licensed under the GetNuTool license", 153 | "* https://github.com/3F/GetNuTool", 154 | "*/", 155 | "", 156 | "using System;", 157 | "using System.Collections.Generic;", 158 | "using System.IO;", 159 | "using System.Linq;", 160 | "using System.Text;", 161 | "using System.Text.RegularExpressions;", 162 | "using ICommand = net.r_eg.vsSBE.Actions.ICommand;", 163 | "using ISolutionEvent = net.r_eg.vsSBE.Events.ISolutionEvent;", 164 | "", 165 | "namespace vsSolutionBuildEvent", 166 | "{", 167 | " public class CSharpMode", 168 | " {", 169 | " public static int Init(ICommand cmd, ISolutionEvent evt)", 170 | " {", 171 | " const string _CORE = @\"$(fCore)\";", 172 | " const string _OUTPUT = @\"$(fCoreMin)\";", 173 | "", 174 | " Func quotes = (symbol) => string.Format", 175 | " (@\"", 176 | " (?, string[]> gencomb = (_dict, _size, _rule0) =>", 192 | " {", 193 | " var combination = new char[_size];", 194 | " var set = new List((int)Math.Pow(_dict.Length, _size));", 195 | "", 196 | " int pos = 0;", 197 | " Action generator = null;", 198 | " generator = () =>", 199 | " {", 200 | " for(int i = 0, lim = _size - 1; i < _dict.Length; ++i)", 201 | " {", 202 | " if(pos == 0 && !_rule0(i))", 203 | " {", 204 | " continue;", 205 | " }", 206 | "", 207 | " if(pos < lim)", 208 | " {", 209 | " combination[pos] = _dict[i];", 210 | " ++pos;", 211 | " generator();", 212 | " --pos;", 213 | " }", 214 | " else", 215 | " {", 216 | " combination[pos] = _dict[i];", 217 | " set.Add(new string(combination.ToArray()));", 218 | " }", 219 | " }", 220 | " };", 221 | "", 222 | " generator();", 223 | " return set.ToArray();", 224 | " };", 225 | "", 226 | " var variables = new Dictionary();", 227 | "", 228 | " var cdict = new[]", 229 | " {", 230 | " 'd', 'e', 'f', 'g', 'h', 'i', 'j',", 231 | " 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',", 232 | " 'u', 'v', 'w', 'x', 'y', 'z',", 233 | " 'D', 'E', 'F', 'G', 'H', 'I', 'J',", 234 | " 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',", 235 | " 'U', 'V', 'W', 'X', 'Y', 'Z',", 236 | " 'a', 'b', 'c', 'A', 'B', 'C',", 237 | " '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',", 238 | " '_'", 239 | " };", 240 | "", 241 | " Func rule = (i) => { return char.IsLetter(cdict[i]) || cdict[i] == '_'; };", 242 | " var vdict1 = gencomb(cdict, 1, rule);", 243 | " var vdict2 = gencomb(cdict, 2, rule);", 244 | "", 245 | " var vdict = new string[vdict1.Length + vdict2.Length];", 246 | " vdict1.CopyTo(vdict, 0);", 247 | " vdict2.CopyTo(vdict, vdict1.Length);", 248 | "", 249 | " // to skip processing for:", 250 | " var exvar = new string[] { \"true\", \"false\" };", 251 | "", 252 | " // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/", 253 | " var rsvwords = new[] { \"do\", \"in\", \"is\", \"as\", \"if\", \"by\", \"on\" };", 254 | "", 255 | " using(var reader = new StreamReader(_CORE, Encoding.UTF8, true))", 256 | " {", 257 | " string content = reader.ReadToEnd();", 258 | "", 259 | " // protect strings", 260 | "", 261 | " var strings = new Dictionary();", 262 | " uint ident = 0;", 263 | " content = Regex.Replace", 264 | " (", 265 | " content,", 266 | " string.Format(@\"({0}|{1})\", quotes('\"'), quotes('\\'')),", 267 | " (m) =>", 268 | " {", 269 | " ++ident;", 270 | " strings[ident] = m.Groups[1].Value;", 271 | " return string.Format(\"!s{0}!\", ident);", 272 | " },", 273 | " RegexOptions.IgnorePatternWhitespace", 274 | " );", 275 | "", 276 | " // code", 277 | "", 278 | " content = Regex.Replace(content, @\"\", (m) =>", 279 | " {", 280 | " string data = m.Value;", 281 | "", 282 | " // comments", 283 | "", 284 | " data = Regex.Replace(data, @\"\\s*\\/\\*.+?\\*\\/\\s*\", \"\", RegexOptions.Singleline);", 285 | " data = Regex.Replace(data, @\"\\s*\\/\\/.+?$\", \"\", RegexOptions.Multiline);", 286 | "", 287 | " // shorten variables", 288 | " // TODO: sort by popularity of use with 1 byte priority", 289 | "", 290 | " variables.Clear();", 291 | " uint uniqVars = 0;", 292 | "", 293 | " Func allocvar = (vname) =>", 294 | " {", 295 | " if(uniqVars + 1 > vdict.Length) throw new OverflowException(\"vdict does not contain data for new vars\");", 296 | " do", 297 | " {", 298 | " variables[vname] = vdict[uniqVars++];", 299 | " }", 300 | " while(rsvwords.Contains(variables[vname]));", 301 | "", 302 | " return variables[vname];", 303 | " };", 304 | "", 305 | " Func shname = (_m, l, vname, r) =>", 306 | " {", 307 | " if(exvar.Contains(vname) /*TODO: L-66 || variables.ContainsValue(vname)*/) return _m.Value;", 308 | " if(variables.ContainsKey(vname)) return l + variables[vname] + r;", 309 | "", 310 | " return l + allocvar(vname) + r;", 311 | " };", 312 | "", 313 | " Func shnameLArgs = (vname) =>", 314 | " {", 315 | " if(variables.ContainsKey(vname)) return variables[vname];", 316 | " return allocvar(vname);", 317 | " };", 318 | "", 319 | " data = Regex.Replace(data, @\"([\\s;},])String([\\s.(]+)\", \"$1string$2\");", 320 | " data = Regex.Replace(data, @\"[sS]tring\\s*\\.\\s*Empty\", \"\\\"\\\"\");", 321 | " data = Regex.Replace(data, @\"\\s*const\\s+[sS]tring\\s+\", \"var \");", 322 | " data = Regex.Replace(data, @\"([;(){}]\\s*)\\w+(?:\\s*\\[\\])?\\s+(\\w+)\\s*(in|=)\\s*\", \" $1 var $2 $3 \");", 323 | " data = Regex.Replace(data, @\"\\s*([{}()=+\\-\\[\\]*?!@,;.])\\s*\", \"$1\");", 324 | "", 325 | " data = Regex.Replace", 326 | " (", 327 | " data,", 328 | " @\"(?:", 329 | " (?'type'", 330 | " \\w+\\s*<[\\w_<,\\s>\\[\\]]+>", 331 | " |", 332 | " \\w+[\\(\\s]*", 333 | " )", 334 | " \\s+", 335 | " (?'name'\\w+)", 336 | " \\s*", 337 | " (?'lim'", 338 | " (?:[+\\-*\\/]?=|\\s+in\\s+|[,)]|\\s*;)", 339 | " )", 340 | " |", 341 | " (?'fl'[(\\s])*(?'lmbd'[^.()=]+?)(?'fr'[)\\s]*)=>", 342 | " )", 343 | " \",", 344 | " (_m) =>", 345 | " {", 346 | " var vname = _m.Groups[\"name\"];", 347 | " if(vname.Success)", 348 | " {", 349 | " return shname(_m, _m.Groups[\"type\"].Value + \" \", vname.Value, _m.Groups[\"lim\"].Value);", 350 | " }", 351 | "", 352 | " var lmbd = _m.Groups[\"lmbd\"];", 353 | " if(lmbd.Success)", 354 | " {", 355 | " var sb = new StringBuilder();", 356 | " foreach(string arg in lmbd.Value.Split(new[] { ',' }))", 357 | " {", 358 | " sb.Append(shnameLArgs(arg));", 359 | " sb.Append(',');", 360 | " }", 361 | "", 362 | " sb.Remove(sb.Length - 1, 1);", 363 | " string fargs = sb.ToString();", 364 | "", 365 | " string fl = _m.Groups[\"fl\"].Value;", 366 | " string fr = _m.Groups[\"fr\"].Value;", 367 | "", 368 | " if(!lmbd.Value.Contains(',') && fr == \")\") fl = fr = \"\";", 369 | "", 370 | " return string.Format(\"{0}{1}{2}=>\", fl, fargs, fr);", 371 | " }", 372 | "", 373 | " return _m.Value;", 374 | " },", 375 | " RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase", 376 | " );", 377 | "", 378 | " // using of variables", 379 | " data = Regex.Replace", 380 | " (", 381 | " data,", 382 | " @\"(?'def'^|[\\s}]else\\s|\\s+in\\s+|(?<==)>|[!={};:\\[(),?+\\-|&])", 383 | " \\s*", 384 | " (?'name'\\w+)", 385 | " (?'exc'[<>]*)?", 386 | " \",", 387 | " (Match _m) =>", 388 | " {", 389 | " var def = _m.Groups[\"def\"].Value;", 390 | " var vname = _m.Groups[\"name\"].Value;", 391 | " var exc = _m.Groups[\"exc\"].Value;", 392 | "", 393 | " if(exc.IndexOfAny(new[] { '<', '>' }) != -1) return _m.Value;", 394 | "", 395 | " if(!Regex.IsMatch(vname, \"^[a-zA-Z_]\")) return _m.Value;", 396 | "", 397 | " if(!variables.ContainsKey(vname))", 398 | " {", 399 | " return def + vname + exc;", 400 | " }", 401 | " return def + variables[vname] + exc;", 402 | " },", 403 | " RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase | RegexOptions.Multiline", 404 | " );", 405 | "", 406 | " // predefined", 407 | "", 408 | " data = data.Replace(\"StringComparison.OrdinalIgnoreCase\", \"(StringComparison)5\");", 409 | " data = data.Replace(\"StringComparison.Ordinal\", \"(StringComparison)4\");", 410 | " data = data.Replace(\"SearchOption.AllDirectories\", \"(SearchOption)1\");", 411 | " data = data.Replace(\"FileMode.Open\", \"(FileMode)3\");", 412 | " data = data.Replace(\"FileAccess.Read\", \"(FileAccess)1\");", 413 | " data = data.Replace(\"UriKind.Relative\", \"(UriKind)2\");", 414 | " data = data.Replace(\"FileMode.Create\", \"(FileMode)2\");", 415 | " data = data.Replace(\"CompressionOption.Maximum\", \"(CompressionOption)1\");", 416 | " data = data.Replace(\"StringSplitOptions.RemoveEmptyEntries\", \"(StringSplitOptions)1\");", 417 | "", 418 | " // 0", 419 | " data = data.Replace(\"TargetMode.Internal\", \"0\");", 420 | " data = data.Replace(\"SearchOption.TopDirectoryOnly\", \"0\");", 421 | "", 422 | " return data;", 423 | " },", 424 | " RegexOptions.Singleline);", 425 | "", 426 | " // common rules", 427 | "", 428 | " content = content.Replace(\"\\r\", \"\").Replace(\"\\n\", \"\");", 429 | " content = Regex.Replace(content, @\"\\s{2,}\", \" \");", 430 | " content = Regex.Replace(content, @\"\\s*([=,()\\[\\];:.&|{}\\/<>]+)\\s*\", \"$1\");", 431 | "", 432 | " /* XML */", 433 | "", 434 | " Action, int> writeMap = (vars, part) =>", 435 | " {", 436 | " using(var wmap = new StreamWriter(string.Format(\"{0}.{1}.map\", _OUTPUT, part), false, new UTF8Encoding(false)))", 437 | " {", 438 | " string map = string.Empty;", 439 | " foreach(var v in vars) map += string.Format(\"{0}={1}{2}\", v.Value, v.Key, Environment.NewLine);", 440 | " wmap.Write(map);", 441 | " }", 442 | " };", 443 | " writeMap(variables, 0);", 444 | "", 445 | " // XML rules", 446 | "", 447 | " content = Regex.Replace(content, @\"\", \"\");", 448 | " content = Regex.Replace(content, @\">\\s+<\", \"><\");", 449 | " content = Regex.Replace(content, @\"\\s+\\/>\", \"/>\");", 450 | "", 451 | " // recover strings", 452 | "", 453 | " content = Regex.Replace(content, @\"!s(\\d+)!\", (m) => {", 454 | " return strings[uint.Parse(m.Groups[1].Value)];", 455 | " });", 456 | "", 457 | " // xml Tasknames", 458 | "", 459 | " variables.Clear();", 460 | " uint uniqt = 0;", 461 | " content = Regex.Replace(content, @\"TaskName\\s*=\\s*\"\"(?'name'\\S+)\"\"\", (_m) =>", 462 | " {", 463 | " var tname = _m.Groups[\"name\"].Value;", 464 | "", 465 | " variables[tname] = vdict[uniqt++];", 466 | "", 467 | " return \"TaskName=\\\"\" + variables[tname] + \"\\\"\";", 468 | " });", 469 | "", 470 | " content = Regex.Replace(content, @\"(?'l'<\\/?)(?'name'[a-z0-9A-Z\\-_]+)\", (_m) =>", 471 | " {", 472 | " var tname = _m.Groups[\"name\"].Value;", 473 | "", 474 | " if(variables.ContainsKey(tname))", 475 | " {", 476 | " return _m.Groups[\"l\"].Value + variables[tname];", 477 | " }", 478 | "", 479 | " return _m.Value;", 480 | " });", 481 | "", 482 | " // XML rules - Post filter", 483 | "", 484 | " content = Regex.Replace(content, @\"\\s+ParameterType\\s*=\\s*\"\"System.String\"\"\\s*\", \" \");", 485 | " content = Regex.Replace(content, @\"\\s+Required\\s*=\\s*\"\"\\S+\"\"\\s*\", \" \");", 486 | " content = Regex.Replace(content, @\"\\s+(\\/)?>\", \"$1>\");", 487 | " content = Regex.Replace(content, @\"'\\s*==\\s*'\", \"'=='\");", 488 | "", 489 | " using(var writer = new StreamWriter(_OUTPUT, false, new UTF8Encoding(false)))", 490 | " writer.Write(content);", 491 | "", 492 | " writeMap(variables, 1);", 493 | " Console.WriteLine(\"{0} -> {1}\", _CORE, _OUTPUT);", 494 | " }", 495 | "", 496 | " return 0;", 497 | " }", 498 | " }", 499 | "}" 500 | ] 501 | } 502 | }, 503 | { 504 | "Enabled": true, 505 | "Name": "Packer", 506 | "Caption": ".packer at /embedded", 507 | "SupportSBEScripts": false, 508 | "Mode": { 509 | "$type": "net.r_eg.vsSBE.Events.ModeCSharp, vsSolutionBuildEvent", 510 | "Type": "CSharp", 511 | "References": [ 512 | "System.dll", 513 | "System.Core.dll" 514 | ], 515 | "SmartReferences": true, 516 | "GenerateInMemory": true, 517 | "TreatWarningsAsErrors": false, 518 | "WarningLevel": 4, 519 | "FilesMode": false, 520 | "CachingBytecode": false, 521 | "Command__": [ 522 | "/*", 523 | "* Copyright (c) 2015 Denis Kuzmin github/3F", 524 | "*", 525 | "* Licensed under the GetNuTool license", 526 | "* https://github.com/3F/GetNuTool", 527 | "*/", 528 | "", 529 | "using System;", 530 | "using System.Collections.Generic;", 531 | "using System.IO;", 532 | "using System.Linq;", 533 | "using System.Text;", 534 | "using System.Text.RegularExpressions;", 535 | "using ICommand = net.r_eg.vsSBE.Actions.ICommand;", 536 | "using ISolutionEvent = net.r_eg.vsSBE.Events.ISolutionEvent;", 537 | "", 538 | "namespace vsSolutionBuildEvent", 539 | "{", 540 | " public class CSharpMode", 541 | " {", 542 | " public static int Init(ICommand cmd, ISolutionEvent evt)", 543 | " {", 544 | " const string _CORE = @\"$(fCoreMin)\";", 545 | " const string _OUTPUT = @\"$(fPacked)\";", 546 | " const string _EMBDTPL = @\"$(fEmbd)\";", 547 | " const string _P_VER = @\"$(pVer)\";", 548 | "", 549 | " Func quotes = (symbol) =>", 550 | " {", 551 | " return string.Format", 552 | " (@\"", 553 | " (?> scalc = (content) =>", 570 | " {", 571 | " var data = new Dictionary(); // \"(start) -> \"(length)", 572 | "", 573 | " var matches = Regex.Matches(content, quotes('\"'), RegexOptions.IgnorePatternWhitespace);", 574 | " foreach(Match m in matches) {", 575 | " data[m.Index] = m.Length;", 576 | " }", 577 | " return data;", 578 | " };", 579 | "", 580 | " Func, bool> isInsideString = (idx, strings) =>", 581 | " {", 582 | " foreach(var s in strings)", 583 | " {", 584 | " if(idx > s.Key && idx < (s.Key + s.Value)) {", 585 | " return true;", 586 | " }", 587 | " }", 588 | " return false;", 589 | " };", 590 | "", 591 | " Func, string[]> gencomb = (_dict, _size, _rule0) =>", 592 | " {", 593 | " var combination = new char[_size];", 594 | " var set = new List((int)Math.Pow(_dict.Length, _size));", 595 | "", 596 | " int pos = 0;", 597 | " Action generator = null;", 598 | " generator = () =>", 599 | " {", 600 | " for(int i = 0, lim = _size - 1; i < _dict.Length; ++i)", 601 | " {", 602 | " if(pos == 0 && !_rule0(i)) {", 603 | " continue;", 604 | " }", 605 | "", 606 | " if(pos < lim) {", 607 | " combination[pos] = _dict[i];", 608 | " ++pos;", 609 | " generator();", 610 | " --pos;", 611 | " }", 612 | " else {", 613 | " combination[pos] = _dict[i];", 614 | " set.Add(new String(combination.ToArray()));", 615 | " }", 616 | " }", 617 | " };", 618 | "", 619 | " generator();", 620 | " return set.ToArray();", 621 | " };", 622 | "", 623 | " var variables = new Dictionary();", 624 | "", 625 | " var cdict = new[]", 626 | " {", 627 | " '-', '[', ']', ';', '.', ',', ':', '+', '{', '}', '_',", 628 | " 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',", 629 | " 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',", 630 | " 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',", 631 | " '4', '5', '6', '7', '8', '9',", 632 | " '$', '#', '@', '`', '?',", 633 | " // '!',", 634 | " };", 635 | "", 636 | " var vdict = gencomb(cdict, 1, (i) => { return !char.IsDigit(cdict[i]); });", 637 | "", 638 | " // to skip processing for:", 639 | " var exword = new[] { \"\" };", 640 | " int skipFirst = 110;", 641 | "", 642 | " const string rlexemes = @\"(?:", 643 | " (?'wrd'", 644 | " Console\\s*\\.\\s*WriteLine\\(\\s*", 645 | " | Console\\s*\\.\\s*Error\\s*\\.\\s*WriteLine\\(\\s*", 646 | " | string\\.IsNullOrEmpty\\(\\s*", 647 | " | Microsoft\\.Build\\.Tasks\\.", 648 | " | Console\\.Write\\(", 649 | " | \\.Trim\\(\\)", 650 | " | ServicePointManager\\.SecurityProtocol", 651 | " | packages\\.config", 652 | " )", 653 | " |", 654 | " (?'ld'%%?0[aA])?", 655 | " (?'cls'[a-z0-9A-Z_\\-]+)", 656 | " )\";", 657 | "", 658 | " using(var reader = new StreamReader(_CORE, System.Text.Encoding.UTF8, true))", 659 | " {", 660 | " var content = reader.ReadToEnd();", 661 | "", 662 | " content = content.Replace(\"%\", \"%%\");", 663 | " ", 664 | " // Protecting data outside strings only:", 665 | " content = Regex.Replace(content, @\"[<|>&]\", (m) => isInsideString(m.Index, scalc(content)) ? m.Value : \"^\" + m.Value);", 666 | "", 667 | " // lexemes via vars", 668 | "", 669 | " var lstat = new Dictionary();", 670 | " foreach(Match m in Regex.Matches(content, rlexemes, RegexOptions.IgnorePatternWhitespace))", 671 | " {", 672 | " var wrd = m.Groups[\"wrd\"];", 673 | " var cls = m.Groups[\"cls\"];", 674 | "", 675 | " var vname = wrd.Success ? wrd.Value : cls.Value;", 676 | "", 677 | " if(vname.Length < 4) { // minimal is 3: %a%", 678 | " continue;", 679 | " }", 680 | "", 681 | " if(exword.Contains(vname)) {", 682 | " continue;", 683 | " }", 684 | "", 685 | " if(!lstat.ContainsKey(vname)) {", 686 | " lstat[vname] = -1 * (vname.Length + 7); //for init: set a= + length + &", 687 | " }", 688 | " lstat[vname] += (vname.Length - 3); //for use: % + a + %", 689 | " }", 690 | " ", 691 | " uint uniqVars = 0;", 692 | " variables.Clear();", 693 | " var prio = lstat.Where(x => x.Value > 0).OrderByDescending(x => x.Value).Take(vdict.Length);", 694 | " var defv = \"\";", 695 | "", 696 | " content = Regex.Replace(content, rlexemes, (m) => ", 697 | " {", 698 | " if(m.Index < skipFirst) {", 699 | " return m.Value;", 700 | " }", 701 | "", 702 | " var wrd = m.Groups[\"wrd\"];", 703 | " var cls = m.Groups[\"cls\"];", 704 | " var ld = m.Groups[\"ld\"].Value;", 705 | "", 706 | " var vname = wrd.Success ? wrd.Value : cls.Value;", 707 | "", 708 | " if(prio.All(x => x.Key != vname)) {", 709 | " return m.Value;", 710 | " }", 711 | "", 712 | " if(variables.ContainsKey(vname)) {", 713 | " return ld + variables[vname];", 714 | " }", 715 | "", 716 | " if(uniqVars + 1 > vdict.Length) {", 717 | " throw new OverflowException(\"vdict does not contain data for new vars\");", 718 | " }", 719 | "", 720 | " var nv = vdict[uniqVars++];", 721 | "", 722 | " variables[vname] = string.Format(\"%{0}%\", nv);", 723 | "", 724 | " defv += string.Format(\"set {0}={1}&\", nv, vname);", 725 | " return ld + variables[vname];", 726 | " },", 727 | " RegexOptions.IgnorePatternWhitespace);", 728 | "", 729 | " using(var wmap = new StreamWriter(_OUTPUT + \".p.map\", false, new UTF8Encoding(false)))", 730 | " {", 731 | " string map = string.Empty;", 732 | " foreach(var v in variables) map += string.Format(\"{0}={1}{2}\", v.Value, v.Key, Environment.NewLine);", 733 | " wmap.Write(map);", 734 | " }", 735 | " ", 736 | " // We'll work without double quotes, so we should define all pairs of \"...\" per line", 737 | "", 738 | " var strings = scalc(content);", 739 | "", 740 | " // Now, we should split long strings", 741 | "", 742 | " var lines = new List();", 743 | " ", 744 | " // Protecting from some symbols in zero position via moving to the end of the previous line", 745 | " Action safeAdd = (idx, l) =>", 746 | " {", 747 | " int lofs = idx;", 748 | " while( (content[lofs] == ' ' || content[lofs] == ')' || content[lofs] == '=')", 749 | " ||", 750 | " //TODO: lexemes via vars %a%, %ab%, ... + escaped %%data", 751 | " (content[lofs] == '%' || content[Math.Min(lofs + 1, content.Length - 1)] == '%') ", 752 | " )", 753 | " {", 754 | " ++lofs;", 755 | " }", 756 | "", 757 | " int ofsdelta = lofs - idx;", 758 | " if(ofsdelta > 0)", 759 | " {", 760 | " lines[lines.Count - 1] += content.Substring(idx, ofsdelta);", 761 | " lines.Add(content.Substring(lofs, l - ofsdelta));", 762 | " return;", 763 | " }", 764 | "", 765 | " lines.Add(content.Substring(idx, l));", 766 | " };", 767 | "", 768 | " for(int i = 0, len = $(packmaxline); i < content.Length; i += len)", 769 | " {", 770 | " int rlen = Math.Min(content.Length - i, len);", 771 | " int rpos = i + rlen;", 772 | "", 773 | " bool added = false;", 774 | " foreach(var ifq in strings)", 775 | " {", 776 | " // Protect strings that we saw above", 777 | " if(rpos >= ifq.Key && rpos <= ifq.Key + ifq.Value)", 778 | " {", 779 | " int repos = ((ifq.Key + ifq.Value) - rpos);", 780 | "", 781 | " safeAdd(i, rlen + repos);", 782 | " i += repos;", 783 | "", 784 | " added = true;", 785 | " break;", 786 | " }", 787 | " }", 788 | "", 789 | " if(added) {", 790 | " continue;", 791 | " }", 792 | "", 793 | " // Protecting from escaped chars as ^ + char above", 794 | "", 795 | " int esc = rpos - 1; // the end of the previous line that should be checked on `^` char", 796 | " if(content.Length > esc && content[esc] == '^') {", 797 | " rlen += 1;", 798 | " safeAdd(i, rlen);", 799 | " i += 1;", 800 | " continue;", 801 | " }", 802 | " ", 803 | " safeAdd(i, rlen);", 804 | " }", 805 | "", 806 | " // Now we can define, how it should be written into external file", 807 | "", 808 | " const string corevar = \"tgnt\";", 809 | " content = string.Empty;", 810 | "", 811 | " foreach(var line in lines)", 812 | " {", 813 | " //content += $\"> %{corevar}%{Environment.NewLine}\";", 814 | " string ldata = string.Format(\">%{1}%\\r\\n\", line, corevar);", 815 | "", 816 | " if(ldata.Length >= 2047) {", 817 | " Console.WriteLine(\"[Warn] Length of line {0}\", ldata.Length);", 818 | " }", 819 | " else if(ldata.Length >= 8191) {", 820 | " Console.Error.WriteLine(\"[Error] Length of line {0}\", ldata.Length);", 821 | " }", 822 | " ", 823 | " content += ldata;", 824 | " }", 825 | "", 826 | " // definition of lexemes", 827 | "", 828 | " content = defv.Substring(0, defv.Length - 1) + \"\\r\\n\" + content;", 829 | "", 830 | " // Finally, format script to work with gnt.core", 831 | "", 832 | " using(var tplreader = new StreamReader(_EMBDTPL, System.Text.Encoding.UTF8, true))", 833 | " {", 834 | " content = tplreader.ReadToEnd()", 835 | " .Replace(\"$gnt.core.logic$\", content)", 836 | " .Replace(\"$tpl.corevar$\", corevar)", 837 | " .Replace(\"$core.version$\", _P_VER);", 838 | " }", 839 | "", 840 | " // ", 841 | "", 842 | " using(var writer = new StreamWriter(_OUTPUT, false, new UTF8Encoding(false))) { // do not use BOM ! it failed with initial signature", 843 | " writer.Write(content);", 844 | " }", 845 | " Console.WriteLine(\"{0} -> {1}\", _CORE, _OUTPUT);", 846 | " }", 847 | " ", 848 | " return 0;", 849 | " }", 850 | " }", 851 | "}" 852 | ] 853 | } 854 | }, 855 | { 856 | "Enabled": true, 857 | "Name": "CompressorEmbd", 858 | "Caption": ".compressor at /embedded", 859 | "SupportSBEScripts": false, 860 | "Mode": { 861 | "$type": "net.r_eg.vsSBE.Events.ModeCSharp, vsSolutionBuildEvent", 862 | "Type": "CSharp", 863 | "References": [ 864 | "System.dll", 865 | "System.Core.dll" 866 | ], 867 | "SmartReferences": true, 868 | "GenerateInMemory": true, 869 | "TreatWarningsAsErrors": false, 870 | "WarningLevel": 4, 871 | "FilesMode": false, 872 | "CachingBytecode": false, 873 | "Command__": [ 874 | "/*", 875 | "* Copyright (c) 2015 Denis Kuzmin github/3F", 876 | "*", 877 | "* Licensed under the GetNuTool license", 878 | "* https://github.com/3F/GetNuTool", 879 | "*", 880 | "* Based on compressor from hMSBuild project", 881 | "* https://github.com/3F/hMSBuild", 882 | "*/", 883 | "", 884 | "using System;", 885 | "using System.Collections.Generic;", 886 | "using System.IO;", 887 | "using System.Linq;", 888 | "using System.Text;", 889 | "using System.Text.RegularExpressions;", 890 | "using ICommand = net.r_eg.vsSBE.Actions.ICommand;", 891 | "using ISolutionEvent = net.r_eg.vsSBE.Events.ISolutionEvent;", 892 | "", 893 | "namespace vsSolutionBuildEvent", 894 | "{", 895 | " public class CSharpMode", 896 | " {", 897 | " public static int Init(ICommand cmd, ISolutionEvent evt)", 898 | " {", 899 | " const string _CORE = @\"$(fPacked)\";", 900 | " const string _OUTPUT = @\"$(fPackMin)\";", 901 | "", 902 | " Func, string[]> gencomb = (_dict, _size, _rule0) =>", 903 | " {", 904 | " var combination = new char[_size];", 905 | " var set = new List((int)Math.Pow(_dict.Length, _size));", 906 | "", 907 | " int pos = 0;", 908 | " Action generator = null;", 909 | " generator = () =>", 910 | " {", 911 | " for(int i = 0, lim = _size - 1; i < _dict.Length; ++i)", 912 | " {", 913 | " if(pos == 0 && !_rule0(i)) continue;", 914 | "", 915 | " if(pos < lim)", 916 | " {", 917 | " combination[pos] = _dict[i];", 918 | " ++pos;", 919 | " generator();", 920 | " --pos;", 921 | " }", 922 | " else", 923 | " {", 924 | " combination[pos] = _dict[i];", 925 | " set.Add(new String(combination.ToArray()));", 926 | " }", 927 | " }", 928 | " };", 929 | "", 930 | " generator();", 931 | " return set.ToArray();", 932 | " };", 933 | "", 934 | " Func review = (input) =>", 935 | " {", 936 | " /* predefined parser behaviour */", 937 | " return Regex.Replace(input, @\"\\s*::&:\\s*&?\", \"\\r\\n\");", 938 | " };", 939 | "", 940 | " var variables = new Dictionary();", 941 | " UTF8Encoding utf8noId = new UTF8Encoding(false);", 942 | "", 943 | " var cdict = new[]", 944 | " {", 945 | " 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',", 946 | " 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',", 947 | " 'y', 'z', 'a', 'b', 'c', 'd', '0', '1', '2', '3',", 948 | " '4', '5', '6', '7', '8', '9',", 949 | " // '_'", 950 | " };", 951 | "", 952 | " string[] vdict = gencomb(cdict, 2, (i) => { return char.IsLetter(cdict[i]) || cdict[i] == '_'; });", 953 | "", 954 | " // to skip processing for:", 955 | " var exvar = new[] { \"__p_call\", \"__p_msb\", \"msb.gnt.cmd\" };", 956 | "", 957 | " const string VNAME = \"[a-z_][a-z_0-9]+\";", 958 | " using(var reader = new StreamReader(_CORE, Encoding.UTF8, true))", 959 | " {", 960 | " string content = reader.ReadToEnd();", 961 | "", 962 | " /* set /a ERROR_ codes */", 963 | "", 964 | " var errorsCodes = new Dictionary();", 965 | " content = Regex.Replace", 966 | " (", 967 | " content,", 968 | " @\"set\\s+\\/a\\s+(?'k'ERROR_[^= ]+)\\s*=\\s*(?'v'\\d+)\",", 969 | " (m) =>", 970 | " {", 971 | " errorsCodes[m.Groups[\"k\"].Value] = m.Groups[\"v\"].Value;", 972 | " return string.Empty;", 973 | " }", 974 | " );", 975 | "", 976 | " foreach(var err in errorsCodes)", 977 | " {", 978 | " content = Regex.Replace(", 979 | " content,", 980 | " string.Format(\"({1}{0}{1}|{2}{0}{2})\", err.Key, \"%\", \"!\"),", 981 | " err.Value", 982 | " );", 983 | " }", 984 | "", 985 | "", 986 | " /* Shorten variables & labels */", 987 | "", 988 | " uint uniqVars = 0;", 989 | " content = Regex.Replace", 990 | " (", 991 | " content,", 992 | " @\"(?'def' ", 993 | " set\\s+?", 994 | " (?:\\/\\S\\s+?)?", 995 | " (?:\"\"\\s*?)?", 996 | " )", 997 | " (?'name'\" + VNAME + @\")", 998 | " (?'lim'\\s?\\S?=)\", // aq+=1,.. TODO: aq=aq+1 ; aq=1+aq ...", 999 | " (m) =>", 1000 | " {", 1001 | " var def = m.Groups[\"def\"].Value;", 1002 | " var vname = m.Groups[\"name\"].Value;", 1003 | " var lim = m.Groups[\"lim\"].Value;", 1004 | "", 1005 | " if(exvar.Contains(vname))", 1006 | " {", 1007 | " return m.Groups[0].Value;", 1008 | " }", 1009 | "", 1010 | " if(variables.ContainsKey(vname))", 1011 | " {", 1012 | " return def + variables[vname] + lim;", 1013 | " }", 1014 | "", 1015 | " if(uniqVars + 1 > vdict.Length)", 1016 | " {", 1017 | " throw new OverflowException(\"vdict does not contain data for new vars\");", 1018 | " }", 1019 | " variables[vname] = vdict[uniqVars++];", 1020 | " return def + variables[vname] + lim;", 1021 | " },", 1022 | " RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase", 1023 | " );", 1024 | "", 1025 | " // call :proc p1 p2 ...", 1026 | " content = Regex.Replace", 1027 | " (", 1028 | " content,", 1029 | " @\"(?'def'call\\s+:\" + VNAME + @\"\\s)(?'args'.+?)(?'eol'&|\\||\\r\\n)\",", 1030 | " (m) =>", 1031 | " {", 1032 | " var def = m.Groups[\"def\"].Value;", 1033 | " var cargs = m.Groups[\"args\"].Value;", 1034 | " var eol = m.Groups[\"eol\"].Value;", 1035 | "", 1036 | " return def + Regex.Replace", 1037 | " (", 1038 | " cargs,", 1039 | " @\"(?'split'^|\\s)(?:(?'str'\"\".+?\"\")|(?'name'\" + VNAME + \"))\",", 1040 | " (_m) =>", 1041 | " {", 1042 | " var split = _m.Groups[\"split\"].Value;", 1043 | "", 1044 | " if(_m.Groups[\"str\"].Success)", 1045 | " {", 1046 | " return split + _m.Groups[\"str\"].Value;", 1047 | " }", 1048 | "", 1049 | " var vname = _m.Groups[\"name\"].Value;", 1050 | "", 1051 | " if(exvar.Contains(vname))", 1052 | " {", 1053 | " return split + vname;", 1054 | " }", 1055 | "", 1056 | " if(variables.ContainsKey(vname))", 1057 | " {", 1058 | " return split + variables[vname];", 1059 | " }", 1060 | "", 1061 | " if(uniqVars + 1 > vdict.Length)", 1062 | " {", 1063 | " throw new OverflowException(\"vdict does not contain data for new vars\");", 1064 | " }", 1065 | " variables[vname] = vdict[uniqVars++];", 1066 | " return split + variables[vname];", 1067 | " },", 1068 | " RegexOptions.IgnoreCase | RegexOptions.Multiline", 1069 | " ) + eol;", 1070 | " },", 1071 | " RegexOptions.IgnoreCase", 1072 | " );", 1073 | "", 1074 | " // %name... & !name...", 1075 | " content = Regex.Replace", 1076 | " (", 1077 | " content,", 1078 | " @\"(?'def'(?:[%!]|\\sdefined\\s+))(?'name'\" + VNAME + \")\",", 1079 | " (m) =>", 1080 | " {", 1081 | " var def = m.Groups[\"def\"].Value;", 1082 | " var vname = m.Groups[\"name\"].Value;", 1083 | "", 1084 | " if(!variables.ContainsKey(vname))", 1085 | " {", 1086 | " return def + vname;", 1087 | " }", 1088 | " return def + variables[vname];", 1089 | " },", 1090 | " RegexOptions.IgnoreCase", 1091 | " );", 1092 | "", 1093 | " // labels", 1094 | " content = Regex.Replace", 1095 | " (", 1096 | " content,", 1097 | " @\"(?'def'call\\s*:|^\\s*:|goto\\s*:?)(?'label'\" + VNAME + @\")(?'eol'\\s|&|\\r\\n)\",", 1098 | " (m) =>", 1099 | " {", 1100 | " var def = m.Groups[\"def\"].Value;", 1101 | " var label = m.Groups[\"label\"].Value;", 1102 | " var eol = m.Groups[\"eol\"].Value;", 1103 | "", 1104 | " if(variables.ContainsKey(label))", 1105 | " {", 1106 | " return def + variables[label] + eol;", 1107 | " }", 1108 | "", 1109 | " if(uniqVars + 1 > vdict.Length)", 1110 | " {", 1111 | " throw new OverflowException(\"vdict does not contain data for new labels\");", 1112 | " }", 1113 | " variables[label] = vdict[uniqVars++];", 1114 | " return def + variables[label] + eol;", 1115 | " },", 1116 | " RegexOptions.IgnoreCase | RegexOptions.Multiline", 1117 | " );", 1118 | "", 1119 | "", 1120 | " /* exit/B */", 1121 | "", 1122 | " content = Regex.Replace(content, @\"exit\\s*(?:\\/B\\s*?(?'code'\\d+|(?:!|%)\" +VNAME+ @\"(?:!|%)?)|\\/B)\\s*?\", (m) =>", 1123 | " {", 1124 | " string ret = \"exit/B\";", 1125 | " string code = m.Groups[\"code\"].Value;", 1126 | "", 1127 | " if(m.Groups[\"code\"].Success)", 1128 | " {", 1129 | " // 'exit /B 0' is not equal to 'exit /B' - it will pass the latest raised code i.e. without changing it.", 1130 | " return ret + code;", 1131 | " }", 1132 | " return ret;", 1133 | " },", 1134 | " RegexOptions.IgnoreCase);", 1135 | "", 1136 | "", 1137 | " /* pseudo arguments from labels */", 1138 | "", 1139 | " content = Regex.Replace(content, @\"^\\s*(?'label':\" + VNAME + @\").*?\\r\\n\", (m) =>", 1140 | " {", 1141 | " return m.Groups[\"label\"].Value + \"\\r\\n\";", 1142 | " },", 1143 | " RegexOptions.IgnoreCase | RegexOptions.Multiline);", 1144 | "", 1145 | "", 1146 | " /* comments */", 1147 | "", 1148 | " content = Regex.Replace(content, @\"(^\\s*?(?'l'::!|rem|::)\\s+)(?'d'.*?)\\r\\n\", (m) =>", 1149 | " {", 1150 | " if(m.Groups[\"l\"].Value == \"::!\" || m.Groups[\"d\"].Value.StartsWith(\"Copyright \")) return m.Value;", 1151 | "", 1152 | " return string.Empty;", 1153 | " },", 1154 | " RegexOptions.IgnoreCase | RegexOptions.Multiline);", 1155 | "", 1156 | "", 1157 | " /* syntax */", 1158 | "", 1159 | " content = Regex.Replace(content, @\"(\\r\\n)\\s*\", \"$1\");", 1160 | " content = Regex.Replace(content, @\"\\s+(\\r\\n)\", \"$1\");", 1161 | " content = content.Replace(\"\\r\\n)\", \")\");", 1162 | " content = content.Replace(\"(\\r\\n\", \"(\");", 1163 | "", 1164 | " Func InlineBlocksIf = null;", 1165 | " InlineBlocksIf = (input) =>", 1166 | " {", 1167 | " if(input.IndexOfAny(new[] { '(', ')' }) == -1) return null;", 1168 | " return Regex.Replace", 1169 | " (", 1170 | " input,", 1171 | " @\"", 1172 | " (?'lim'^|\\r\\n|[\\s)&])", 1173 | " (?'cond'else\\s.*|if\\s.+?(?!\\(x86\\).+?))", 1174 | " \\((?'body'", 1175 | " (?>", 1176 | " [^\\(\\)]", 1177 | " |", 1178 | " \\((?)", 1179 | " |", 1180 | " \\)(?<-R>)", 1181 | " )*", 1182 | " (?(R)(?!))", 1183 | " )\\)", 1184 | " \",", 1185 | " (_m) =>", 1186 | " {", 1187 | " string lim = _m.Groups[\"lim\"].Value;", 1188 | " string cond = _m.Groups[\"cond\"].Value;", 1189 | " string body = _m.Groups[\"body\"].Value;", 1190 | "", 1191 | " string ret = InlineBlocksIf(_m.Groups[\"body\"].Value);", 1192 | " if(ret == null) return lim + \"(\" + cond + \"(\" + body + \"))&\";", 1193 | "", 1194 | " return lim + \"(\" + cond + \"(\" + ret + \"))&\";", 1195 | " },", 1196 | " RegexOptions.IgnorePatternWhitespace", 1197 | " );", 1198 | " };", 1199 | " //content = InlineBlocksIf(content);", 1200 | " content = Regex.Replace(content, @\"\\)\\s*&\\s*\\(\\s*else\\s\", \"else \");", 1201 | " content = Regex.Replace(content, @\"\\)\\s*&\\s*\\)\", \"))\");", 1202 | " content = Regex.Replace(content, @\"\\)\\s*&\\s*\\r\\n\", \")\\r\\n\");", 1203 | "", 1204 | " content = Regex.Replace", 1205 | " (", 1206 | " content,", 1207 | " @\"(^(?:setlocal|endlocal|rmdir|shift|call|exit|echo|del|goto|set)[:/\\w\\S ]*)\\r\\n(?![:<])\",", 1208 | " (_m) =>", 1209 | " {", 1210 | " if(_m.Value.IndexOfAny(new[] { '&', '|' }) != -1) return _m.Value;", 1211 | " return _m.Groups[1].Value + \"&\";", 1212 | " },", 1213 | " RegexOptions.Multiline | RegexOptions.IgnoreCase", 1214 | " );", 1215 | " // GetNuTool, Y-84", 1216 | " content = Regex.Replace(content, @\"(?", 1224 | " {", 1225 | " return string.Format(\" in ({0})do {1}\", mfor.Groups[1].Value.Replace(\" \", \"\"), mfor.Groups[2].Value);", 1226 | " },", 1227 | " RegexOptions.IgnoreCase);", 1228 | "", 1229 | " content = Regex.Replace(content, @\"\\s*\\)\\s*(else\\s)\", \")$1\", RegexOptions.IgnoreCase);", 1230 | " content = Regex.Replace(content, @\"\\(\\s+(goto|set|call)\\s+\", \"($1 \", RegexOptions.IgnoreCase);", 1231 | "", 1232 | " Func InlineBlocksFor = null;", 1233 | " InlineBlocksFor = (input) =>", 1234 | " {", 1235 | " return Regex.Replace", 1236 | " (", 1237 | " input,", 1238 | " @\"", 1239 | " (?'lim'^|\\r\\n|[\\s)&])", 1240 | " (?'def'for\\s[^(]+?\\([^)]+?\\)\\s*do\\s*)", 1241 | " \\((?'body'", 1242 | " (?>", 1243 | " [^\\(\\)]", 1244 | " |", 1245 | " \\((?)", 1246 | " |", 1247 | " \\)(?<-R>)", 1248 | " )*", 1249 | " (?(R)(?!))", 1250 | " )\\)", 1251 | " \\s*&?", 1252 | " \",", 1253 | " (_m) =>", 1254 | " {", 1255 | " string lim = _m.Groups[\"lim\"].Value;", 1256 | " string def = _m.Groups[\"def\"].Value;", 1257 | " string body = _m.Groups[\"body\"].Value;", 1258 | "", 1259 | " return lim + \"(\" + def + \"(\" + body + \"))&\";", 1260 | " },", 1261 | " RegexOptions.IgnorePatternWhitespace", 1262 | " );", 1263 | " };", 1264 | " //content = InlineBlocksFor(content);", 1265 | " //content = Regex.Replace(content, @\"\\)\\s*&\\s*:\", \")\\r\\n:\");", 1266 | "", 1267 | "", 1268 | " /* line packing */", 1269 | "", 1270 | " Func splitLongLines = (input, lim, wrd) =>", 1271 | " {", 1272 | " var spl = new StringBuilder(content.Length + 100);", 1273 | " for(int i = 0; i < content.Length;)", 1274 | " {", 1275 | " int start = i;", 1276 | " int end = content.IndexOf(\"\\r\\n\", start + 1);", 1277 | " if(end == -1)", 1278 | " {", 1279 | " spl.Append(content.Substring(start));", 1280 | " break;", 1281 | " }", 1282 | " i = end;", 1283 | "", 1284 | " int len = end - start;", 1285 | " if(len <= lim)", 1286 | " {", 1287 | " spl.Append(content.Substring(start, len));", 1288 | " continue;", 1289 | " }", 1290 | "", 1291 | " int pos = content.IndexOf(wrd, start + lim - wrd.Length);", 1292 | " if(pos == -1)", 1293 | " {", 1294 | " spl.Append(content.Substring(start, end - start));", 1295 | " continue;", 1296 | " }", 1297 | "", 1298 | " string a = content.Substring(start, pos - start);", 1299 | " spl.AppendLine(a);", 1300 | " string b = content.Substring(++pos, end - pos);", 1301 | " spl.Append(b);", 1302 | " }", 1303 | " return spl.ToString();", 1304 | " };", 1305 | " // max 2047 or 8191 (XP+) characters per line", 1306 | " //content = splitLongLines(content, 1700, \"&echo\");", 1307 | "", 1308 | " using(var writer = new StreamWriter(_OUTPUT, false, utf8noId))", 1309 | " writer.Write(review(content));", 1310 | "", 1311 | " Console.WriteLine(\"{0} -> {1}\", _CORE, _OUTPUT);", 1312 | " }", 1313 | "", 1314 | " //File.WriteAllText(_CORE, review(File.ReadAllText(_CORE, Encoding.UTF8)), utf8noId);", 1315 | "", 1316 | " /* map */", 1317 | "", 1318 | " using(var wmap = new StreamWriter(_CORE + \".map\", false, utf8noId))", 1319 | " {", 1320 | " string map = string.Empty;", 1321 | " foreach(var v in variables) map += string.Format(\"{0}={1}{2}\", v.Value, v.Key, Environment.NewLine);", 1322 | " wmap.Write(map);", 1323 | " }", 1324 | "", 1325 | " string mtpl =", 1326 | "@\"", 1327 | "", 1328 | " ", 1329 | "{0}", 1330 | " ", 1331 | "\";", 1332 | "", 1333 | " using(var wmap = new StreamWriter(_CORE + \".map.targets\", false, utf8noId))", 1334 | " {", 1335 | " string map = string.Empty;", 1336 | " foreach(var v in variables)", 1337 | " {", 1338 | " map += string.Format", 1339 | " (", 1340 | " \"{3}\",", 1341 | " \"$\",", 1342 | " v.Value,", 1343 | " v.Key,", 1344 | " Environment.NewLine", 1345 | " );", 1346 | " }", 1347 | " wmap.Write(string.Format(mtpl, map));", 1348 | " }", 1349 | "", 1350 | " return 0;", 1351 | " }", 1352 | " }", 1353 | "}" 1354 | ] 1355 | } 1356 | }, 1357 | { 1358 | "Enabled": true, 1359 | "Name": "Validating", 1360 | "Caption": "Validating cores ...", 1361 | "Mode": { 1362 | "$type": "net.r_eg.vsSBE.Events.ModeScript, vsSolutionBuildEvent", 1363 | "Type": "Script", 1364 | "Command__": [ 1365 | "#[IO copy.file(\"$(dobj)gnt.bat\", \"$(dobj)gnt.full.bat\", true)]", 1366 | "#[IO copy.file(\"$(dobj)gnt.minified.bat\", \"$(dobj)gnt.bat\", true)]", 1367 | "#[IO delete.files({\"$(dobj)gnt.minified.bat\"})]", 1368 | "", 1369 | "#[IO writeLine(STDOUT):#[File cmd(\"cd $(dobj) & .\\gnt.bat -unpack\", 400)]]", 1370 | "", 1371 | "#[var hCore1 = #[Func hash.SHA1(\"$([System.IO.File]::ReadAllText('$(dobj)gnt.min.core'))\")]]", 1372 | "#[var hCore2 = #[Func hash.SHA1(\"$([System.IO.File]::ReadAllText('$(dobj)gnt.core'))\")]]", 1373 | "", 1374 | "#[IO writeLine(STDOUT):", 1375 | "Core 1: 0x#[$(hCore1)] : gnt.min.core", 1376 | "Core 2: 0x#[$(hCore2)] : gnt.core", 1377 | "]", 1378 | "", 1379 | "#[( \"$(hCore1)\" != \"$(hCore2)\" )", 1380 | "{", 1381 | " #[IO writeLine(STDERR): Core 1 != Core 2]", 1382 | " #[Build cancel = true]", 1383 | "}]", 1384 | "" 1385 | ] 1386 | } 1387 | }, 1388 | { 1389 | "Enabled": true, 1390 | "Name": "CsEditions", 1391 | "Caption": "Generate Cs editions ...", 1392 | "SupportSBEScripts": false, 1393 | "IgnoreIfBuildFailed": true, 1394 | "Mode": { 1395 | "$type": "net.r_eg.vsSBE.Events.ModeCSharp, vsSolutionBuildEvent", 1396 | "Type": "CSharp", 1397 | "References": [ 1398 | "System.dll" 1399 | ], 1400 | "SmartReferences": true, 1401 | "GenerateInMemory": true, 1402 | "TreatWarningsAsErrors": false, 1403 | "WarningLevel": 4, 1404 | "FilesMode": false, 1405 | "CachingBytecode": false, 1406 | "Command__": [ 1407 | "using System.Collections.Generic;", 1408 | "using System.Text;", 1409 | "using System.Text.RegularExpressions;", 1410 | "using System.IO;", 1411 | "using ICommand = net.r_eg.vsSBE.Actions.ICommand;", 1412 | "using ISolutionEvent = net.r_eg.vsSBE.Events.ISolutionEvent;", 1413 | "", 1414 | "namespace vsSolutionBuildEvent", 1415 | "{", 1416 | " public class CSharpMode", 1417 | " {", 1418 | " public static int Init(ICommand cmd, ISolutionEvent evt)", 1419 | " {", 1420 | " string core = File.ReadAllText(@\"$(dobj)gnt.min.core\");", 1421 | "", 1422 | " var sb = new StringBuilder();", 1423 | " foreach(Match m in Regex.Matches(core, @\"Using Namespace=\"\"([a-z_0-9.]+)\"\"\", RegexOptions.IgnoreCase))", 1424 | " {", 1425 | " sb.AppendLine(\"using \" + m.Groups[1].Value + \";\");", 1426 | " }", 1427 | "", 1428 | " var pDefault = new Dictionary() { {\"wpath\", \"\"} };", 1429 | " foreach(Match m in Regex.Matches", 1430 | " (", 1431 | " Regex.Match(core, @\"PropertyGroup>(.+?)|.+?>)([^<]+?)<\"", 1433 | " ))", 1434 | " {", 1435 | " if(!pDefault.ContainsKey(m.Groups[1].Value))", 1436 | " pDefault[m.Groups[1].Value] = m.Groups[2].Value;", 1437 | " }", 1438 | "", 1439 | " string cs = \"/* GetNuTool $(pVerPrintApp) for C# (c) Denis Kuzmin github/3F */\"", 1440 | " + Regex.Match(core, @\"\", RegexOptions.IgnoreCase).Groups[1].Value;", 1441 | "", 1442 | " var props = new List();", 1443 | " int tmodeIndex = cs.IndexOf(\"tmode\"); // Global Properties before tmode use.", 1444 | " int globalProps = 0;", 1445 | " cs = Regex.Replace(cs, @\"@?\"\"\\s*\\$\\(([a-zA-Z_0-9.]+)\\)\\s*\"\"\", (m) =>", 1446 | " {", 1447 | " if(m.Groups[1].Index < tmodeIndex) globalProps = props.Count;", 1448 | " string name = m.Groups[1].Value;", 1449 | " if(name == \"GetNuTool\") return m.Value;", 1450 | " if(name == \"break\") name = \"@\" + name;", 1451 | " if(!props.Contains(name)) props.Add(name);", 1452 | " return name;", 1453 | " })", 1454 | " .Replace(\"$$(GetNuTool)\", \"$(pVerPrintApp)\");", 1455 | "", 1456 | " var fields = new StringBuilder();", 1457 | " for(int i = 0; i <= globalProps; ++i)", 1458 | " {", 1459 | " string p = props[i];", 1460 | " string pv = pDefault.ContainsKey(p) ? pDefault[p] : string.Empty;", 1461 | " fields.AppendLine(string.Format", 1462 | " (", 1463 | " \" public string {0}{1} = {2}\\\"{3}\\\";\",", 1464 | " p == \"break\" ? \"@\" : \"\",", 1465 | " p,", 1466 | " pv.Contains(@\"\\\") ? \"@\" : \"\",", 1467 | " pv", 1468 | " ));", 1469 | " }", 1470 | " ", 1471 | " var margs = new StringBuilder();", 1472 | " for(int i = globalProps + 1; i < props.Count; ++i)", 1473 | " {", 1474 | " string p = props[i];", 1475 | " string pv = pDefault.ContainsKey(p) ? pDefault[p] : string.Empty;", 1476 | " margs.Append(string.Format", 1477 | " (", 1478 | " \"string {0}{1} = {2}\\\"{3}\\\", \",", 1479 | " p == \"break\" ? \"@\" : \"\",", 1480 | " p,", 1481 | " pv.Contains(@\"\\\") ? \"@\" : \"\",", 1482 | " pv", 1483 | " ));", 1484 | " }", 1485 | "", 1486 | " sb.AppendLine();", 1487 | " sb.AppendLine(\"namespace net.r_eg\");", 1488 | " sb.AppendLine(\"{\");", 1489 | " sb.AppendLine(\" public class GetNuTool\");", 1490 | " sb.AppendLine(\" {\");", 1491 | " sb.AppendLine(\" public const string VER = \\\"$(pVer)\\\";\");", 1492 | " sb.AppendLine(fields.ToString());", 1493 | " sb.AppendLine(\" /// get / grab / pack (create .nupkg)\");", 1494 | " sb.AppendLine(\"#pragma warning disable//netfx4.0+\");", 1495 | " sb.Append(\" public bool Run(string tmode = \\\"get\\\", \");", 1496 | " sb.Append(margs.Remove(margs.Length - 2, 2).ToString());", 1497 | " sb.AppendLine(\"){\" + cs + \"return true;}\");", 1498 | " sb.AppendLine(\"#pragma warning restore\");", 1499 | " sb.AppendLine(\" }\");", 1500 | " sb.AppendLine(\"}\");", 1501 | "", 1502 | " using(var w = new StreamWriter(@\"$(dobj)GetNuTool.cs\", false, new UTF8Encoding(false)))", 1503 | " w.Write(sb.ToString());", 1504 | " ", 1505 | " return 0;", 1506 | " }", 1507 | " }", 1508 | "}" 1509 | ] 1510 | } 1511 | } 1512 | ], 1513 | "PostBuild": [ 1514 | { 1515 | "Enabled": true, 1516 | "Name": "ActBin", 1517 | "Caption": "Binaries & tools ...", 1518 | "IgnoreIfBuildFailed": true, 1519 | "Mode": { 1520 | "$type": "net.r_eg.vsSBE.Events.ModeScript, vsSolutionBuildEvent", 1521 | "Type": "Script", 1522 | "Command__": [ 1523 | "#[IO copy.file", 1524 | "(", 1525 | " {", 1526 | " \"License.txt\",", 1527 | " \"changelog.txt\",", 1528 | " \".version\",", 1529 | " \".gitattributes\",", 1530 | " \"Readme.md\",", 1531 | " \"tests.bat\"", 1532 | " },", 1533 | " \"$(odir)\",", 1534 | " true", 1535 | ")]", 1536 | "", 1537 | "#[IO copy.file({ \"tests/*.bat\" }, \"$(odir)/tests/\", true)]", 1538 | "", 1539 | "#[IO copy.file(\"$(dobj)gnt.min.core\", \"$(odir)core/gnt.core\", true)]", 1540 | "#[IO copy.file(\"$(dobj)GetNuTool.cs\", \"$(odir)csharp/\", true)]", 1541 | "#[IO copy.file(\"$(dobj)gnt.bat\", \"$(odir)shell/batch/\", true)]", 1542 | "#[IO copy.file(\"caller.bat\", \"$(odir)wrappers/batch/gnt.bat\", true)]", 1543 | "", 1544 | "#[IO copy.file", 1545 | "(", 1546 | " { \"$(dobj)*.map\", \"$(dobj)*.map.targets\" },", 1547 | " \"$(odir)maps/\",", 1548 | " true", 1549 | ")]", 1550 | "", 1551 | "", 1552 | "#[$(demoPath = \"$(odir)\\demo\\batch\\\\\")]", 1553 | "#[$(tpackages = '.tools\\packages.config')]", 1554 | "", 1555 | "#[$(vssbePkgV = $([System.Text.RegularExpressions.Regex]::Match('$([System.IO.File]::ReadAllText($(tpackages)))', 'vsSolutionBuildEvent\" version=\"(.+?)\"').Groups[1].Value))]", 1556 | "", 1557 | "#[$(demoCore = \"$(demoPath)vsSolutionBuildEvent.$(vssbePkgV).bat\")]", 1558 | "#[IO copy.file(\"$(dobj)gnt.bat\", \"$(demoCore)\", true)]", 1559 | "", 1560 | "#[var demotpl = #[File get(\"demo.vssbe.bat\")]]", 1561 | "#[IO replace(\"$(demoCore)\", \"@echo off\", \"$(demotpl.Replace('%v%', $(vssbePkgV)))@echo off\")]", 1562 | "", 1563 | "", 1564 | "#[$(shaListDir = $(odir))]", 1565 | "#[$(searchSubDirs = '1')]", 1566 | "#[Core events.Post.item(\"ShaList\").run()]" 1567 | ] 1568 | } 1569 | }, 1570 | { 1571 | "Enabled": false, 1572 | "Name": "ShaList", 1573 | "SupportSBEScripts": false, 1574 | "Mode": { 1575 | "$type": "net.r_eg.vsSBE.Events.ModeCSharp, vsSolutionBuildEvent", 1576 | "Type": "CSharp", 1577 | "References": [ 1578 | "System.dll" 1579 | ], 1580 | "SmartReferences": true, 1581 | "GenerateInMemory": true, 1582 | "TreatWarningsAsErrors": false, 1583 | "WarningLevel": 4, 1584 | "FilesMode": false, 1585 | "CachingBytecode": false, 1586 | "Command__": [ 1587 | "using System;", 1588 | "using System.IO;", 1589 | "using System.Text;", 1590 | "using System.Security.Cryptography;", 1591 | "using ICommand = net.r_eg.vsSBE.Actions.ICommand;", 1592 | "using ISolutionEvent = net.r_eg.vsSBE.Events.ISolutionEvent;", 1593 | "", 1594 | "namespace vsSolutionBuildEvent", 1595 | "{", 1596 | " public class CSharpMode", 1597 | " {", 1598 | " public static int Init(ICommand cmd, ISolutionEvent evt)", 1599 | " {", 1600 | " string dir = @\"$(shaListDir)\".Replace('/', '\\\\');", 1601 | " ", 1602 | " Func _BytesToHexView = (data) =>", 1603 | " {", 1604 | " var ret = new StringBuilder();", 1605 | " foreach(byte b in data) ret.Append(b.ToString(\"x2\"));", 1606 | " return ret.ToString();", 1607 | " };", 1608 | "", 1609 | " var values = new StringBuilder();", 1610 | "", 1611 | " using(SHA1 sha1 = SHA1.Create())", 1612 | " {", 1613 | " foreach(var input in Directory.GetFiles(dir, \"*\", (SearchOption)$(searchSubDirs)))", 1614 | " {", 1615 | " using(var stream = new FileStream(input, FileMode.Open, FileAccess.Read))", 1616 | " values.AppendLine(string.Format", 1617 | " (", 1618 | " \"{0} {1}\",", 1619 | " _BytesToHexView(sha1.ComputeHash(stream)),", 1620 | " input.Replace(dir, \"\")", 1621 | " ));", 1622 | " }", 1623 | " }", 1624 | "", 1625 | " using(var w = new StreamWriter(Path.Combine(dir, \".sha1\"), false, new UTF8Encoding(false)))", 1626 | " w.Write(values.ToString());", 1627 | " ", 1628 | " return 0;", 1629 | " }", 1630 | " }", 1631 | "}" 1632 | ] 1633 | } 1634 | }, 1635 | { 1636 | "Enabled": true, 1637 | "Name": "ActZip", 1638 | "Caption": "Create Zip archive", 1639 | "IgnoreIfBuildFailed": true, 1640 | "Mode": { 1641 | "$type": "net.r_eg.vsSBE.Events.ModeScript, vsSolutionBuildEvent", 1642 | "Type": "Script", 1643 | "Command__": [ 1644 | "#[7z pack.directory(\"$(dbin)raw\", \"$(dbin)GetNuTool.$(pVerPrintFile).zip\")]", 1645 | "", 1646 | "#[IO copy.file(\"$(odir)shell/batch/gnt.bat\", \"$(dbin)\", true)]", 1647 | "", 1648 | "#[$(shaListDir = $(dbin))]", 1649 | "#[$(searchSubDirs = '0')]", 1650 | "#[Core events.Post.item(\"ShaList\").run()]" 1651 | ] 1652 | } 1653 | } 1654 | ] 1655 | } -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2024 Denis Kuzmin github/3F 4 | Copyright (c) GetNuTool contributors https://github.com/3F/GetNuTool/graphs/contributors 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # [GetNuTool](https://github.com/3F/GetNuTool) 2 | 3 | Embeddable Package Manager (+core in .bat); 4 | 🕊 Lightweight tool to Create or Distribute using basic shell scripts (does not require *powershell* or *dotnet-cli*); 5 | *NuGet* / *Chocolatey* client; 6 | 7 | ```r 8 | Copyright (c) 2015-2024 Denis Kuzmin github/3F 9 | ``` 10 | 11 | [ 「 ❤ 」 ](https://3F.github.io/fund) [![License](https://img.shields.io/badge/License-MIT-74A5C2.svg)](https://github.com/3F/GetNuTool/blob/master/License.txt) 12 | [![Build status](https://ci.appveyor.com/api/projects/status/gw8tij2230gwkqs6/branch/master?svg=true)](https://ci.appveyor.com/project/3Fs/getnutool-github/branch/master) 13 | [![release](https://img.shields.io/github/release/3F/GetNuTool.svg)](https://github.com/3F/GetNuTool/releases/latest) 14 | 15 | 16 | ```bash 17 | gnt Fnv1a128 # Get Fnv1a128 package 18 | gnt /t:pack /p:ngin="bin\DllExport" # Create new DllExport package 19 | gnt "Conari;regXwild" # Get Conari & regXwild packages 20 | msbuild gnt.core /p:ngpackages=LuNari/1.6.0 # Use msbuild to get LuNari 1.6.0 21 | gnt Huid/1.0.0:src.zip /t:grab # Grab Huid 1.0 as zip without unpacking 22 | gnt /p:ngconfig="dir\packages.config" # Use specified packages.config 23 | set ngpackages=Conari & gnt # shell scripts 24 | gnt /p:ngpackages=putty.portable/0.69 # chocolatey 25 | /p:ngserver="https://chocolatey.org/api/v2/package/" 26 | ``` 27 | 28 | **[Download](https://github.com/3F/GetNuTool/releases/latest)** all editions: *Core, Minified, Executable, C# version for .NET, ...* 29 | 30 | Official Direct Links: 31 | 32 | * (Windows) Latest stable compiled batch-script [ [gnt.bat](https://3F.github.io/GetNuTool/releases/latest/gnt/) ] `https://3F.github.io/GetNuTool/releases/latest/gnt/` 33 | 34 | 35 | ### Projects based entirely on GetNuTool 36 | 37 | * [netfx4sdk](https://github.com/3F/netfx4sdk) - Developer Pack (SDK). NETFX 4: Visual Studio 2022+ / MSBuild 17+ / or other modern tools; 38 | * [hMSBuild](https://github.com/3F/hMSBuild) - Compiled text-based embeddable pure batch-scripts for searching modern MSBuild instances; 39 | * [.NET DllExport Manager](https://github.com/3F/DllExport/wiki/DllExport-Manager) - Part of the DllExport tool that provides its completely independent management and distribution beyond the NuGet ecosystem. Relies on [MvsSln](https://github.com/3F/MvsSln) as well; 40 | 41 | 42 | ## Why GetNuTool 43 | 44 | ```bash 45 | > gnt # via single shell script 46 | > msbuild gnt.core # via MSBuild engine 47 | [NuGet gnt.raw("/t:pack /p:ngin=7z.Libs")] # via SobaScript 48 | new GetNuTool() # .NET(netfx 4.0+, .NET 5+, .NET Core, Mono) C# 49 | ``` 50 | 51 | Lightweight Portable and completely Embeddable (+core in .bat) package tool to create or distribute everything from anything. 52 | 53 | Back in those days it was originally developed as an alternative to solution level limitations, i.e. [github.com/NuGet/Home/issues/1521](https://github.com/NuGet/Home/issues/1521). In attempt to provide a tool to easily maintain projects, libraries, and other related build processes; For all projects at once at the solution level and of course for each separately if necessary. 54 | 55 | For example, it was designed to be more friendly to such NuGet packages: 56 | * [vsSolutionBuildEvent](https://www.nuget.org/packages/vsSolutionBuildEvent) (before, aka [vsSBE.CI.MSBuild](https://www.nuget.org/packages/vsSBE.CI.MSBuild/)) 57 | * [7z.Libs](https://www.nuget.org/packages/7z.Libs/) 58 | * [DllExport](https://github.com/3F/DllExport) 59 | * [ILAsm](https://www.nuget.org/packages/ILAsm/) 60 | 61 | However! GetNuTool has more powerful ways even for standard NuGet packages providing a wider range of use cases. 62 | 63 | * [Conari](https://github.com/3F/Conari), [Fnv1a128](https://github.com/3F/Fnv1a128), [MvsSln](https://github.com/3F/MvsSln), [regXwild](https://github.com/3F/regXwild), ... 64 | 65 | ### Key Features 66 | 67 | * Install *.nupkg* packages from remote NuGet (or like: chocolatey, ...) servers. 68 | * Grab or Install any *zipped* packages from direct sources (local, remote http, https, ftp, ...). 69 | * Controlled unpacking of all received packages. Modes: `get` or `grab` 70 | * Hash values control using [`sha1`](https://en.wikipedia.org/wiki/SHA-1) for receiving every package if used unsecured channels (~windows xp) etc. 71 | * Creating new NuGet packages *.nupkg* from *.nuspec*. 72 | * Two supported formats: xml *packages.config* (+extra: output, sha1) and inline records. 73 | * Inline records and packages.config are fully compatible between, and config has backward compatibility with original packages.config 74 | * Configurable custom folders for every receiving. 75 | * Request to the server only if the package is not installed. 76 | * Supports proxy with custom credential. 77 | * Default settings are overridden through an environment variables: default .config files, NuGet server, etc. 78 | * The ability to create *one click* ~8 KB .bat wrappers for any packages. Try for example [vsSolutionBuildEvent.bat](https://github.com/3F/GetNuTool/blob/master/demo/vsSolutionBuildEvent.bat) 79 | * Easy integration into any scripts such as pure batch-script [netfx4sdk](https://github.com/3F/netfx4sdk), [DllExport](https://github.com/3F/DllExport/wiki/DllExport-Manager), [hMSBuild](https://github.com/3F/hMSBuild) 80 | * C# projects support via GetNuTool.cs 81 | 82 | Note: 83 | 84 | * Dependencies are not considered. 85 | * Doesn't manage projects or solutions files. You need [MvsSln](https://github.com/3F/MvsSln) or anything else together with. 86 | * NuGet events *(Init.ps1, Install.ps1, Uninstall.ps1) from /tools* will not be launched automatically. 87 | * To use events (from Visual Studio, MSBuild, NuGet, etc.), you can with [vsSolutionBuildEvent](https://github.com/3F/vsSolutionBuildEvent), or [vsCommandEvent](https://github.com/3F/vsCommandEvent), or configure it like [DllExport](https://github.com/3F/DllExport) project, or command it manually. 88 | 89 | ## tModes and Commands 90 | 91 | ### `get` 92 | 93 | For receiving packages or zipped files from local or remote source, then installing / extracting. 94 | 95 | The `get` is used by default but you can also specify `/t:get` 96 | 97 | Property | Description | Default values 98 | -----------|---------------------------------------------------------------|----------------- 99 | ngconfig | Define *.config* files. | 1.9+ `packages.config;.tools\packages.config` 100 | ngserver | Define server. | 1.0+ `https://www.nuget.org/api/v2/package/` 101 | ngpackages | List of packages. Disables *ngconfig* if specified. | 102 | ngpath | Common path for all packages. | 1.0+ `packages` 103 | wpath | *1.4+* To change working directory. | 1.4+ *(The absolute path of the directory where the GetNuTool is located)* 104 | proxycfg | *1.6.2+* To configure connection via proxy. | 105 | ssl3 | *1.9+* Do **not** drop legacy ssl3, tls1.0, tls1.1 if `true`. | 106 | break | *1.9+* Disable the break on first package error if `no` | 107 | 108 | 109 | #### Package List Format 110 | 111 | Attribute | Description | Example 112 | ----------|----------------------------------------------|------------------------------ 113 | id | Identifier of package. | `Conari` 114 | version | *(Optional)* Package version. | `1.5.0` or `1.5-beta2` or `1.5-RC` etc. 115 | output | *(Optional)* Where to store package data. | `../tests/case1` 116 | sha1 | *(Optional)* Expected sha1 for this package. | `eead8f5c1fdff2abd4da7d799fbbe694d392c792` 117 | 118 | **Note:** 119 | 120 | * As of version 1.2+, attributes are now case sensitive. Please use lowercase for `id`, `version`, `output`, `sha1`. 121 | * It will link to the **latest** available version if `version` attribute is not defined. 122 | * `output` attribute is relative to `ngpath`. You can also use absolute path. 123 | * `sha1` activates security check before every install / extracting. It useful when connection is not secure like on windows xp with obsolete ciphers. But please note: some servers (like official NuGet) may repackage .nupkg for some purposes, such as adding *.signature.p7s* etc. This of course changes sha1 hash value that you need to check. 124 | * `id` allows only `a-z` `A-Z` `0-9` `.` `-` `_` symbols without whitespaces. 125 | 126 | ##### *ngpackages* 127 | 128 | ```ps 129 | id[/version][?sha1][:path];id2[/version][?sha1][:path];... 130 | ``` 131 | 132 | delimiters: 133 | 134 | * `;` 1.6+ `Name1;Name2;Name3` 135 | * `|` 1.0+ `Name1|Name2|Name3` 136 | 137 | ```ps 138 | /p:ngpackages=Name1 139 | /p:ngpackages="Name1;Name2" 140 | ``` 141 | 142 | ##### *packages.config* 143 | 144 | ```xml 145 | 146 | 147 | 148 | 149 | 150 | 151 | ``` 152 | 153 | ```ps 154 | /p:ngconfig=".nuget/packages.config" 155 | /p:ngconfig="debug.config;release.config;..." 156 | ``` 157 | 158 | #### Proxy Format 159 | 160 | ```ps 161 | [usr[:pwd]@]host[:port] 162 | ``` 163 | 164 | ```ps 165 | /p:proxycfg="example.com:4321" 166 | ``` 167 | 168 | ### `grab` 169 | 170 | 1.9+ 171 | 172 | Grabs data without unpacking. The available parameters are similar to the `get` above. 173 | 174 | For example: 175 | 176 | ```bat 177 | gnt Huid/1.0.0:src.nupkg /t:grab 178 | ``` 179 | 180 | ```bat 181 | gnt :../netfx4sdk.cmd /t:grab /p:ngserver=https://server/netfx4sdk.cmd 182 | ``` 183 | 184 | ```bat 185 | msbuild gnt.core /t:grab /p:ngpackages=Fnv1a128:src.nupkg 186 | ``` 187 | 188 | ```bat 189 | gnt Huid/1.0.0?24ecda9a4fb8920067df31788d3dea708996ab08:src.nupkg /t:grab 190 | ``` 191 | 192 | ### `pack` 193 | 194 | Creates the new *.nupkg* packages using [*.nuspec*](https://learn.microsoft.com/en-us/nuget/reference/nuspec) specification. 195 | Can also be found in the package folder after using `get`. 196 | 197 | Property | Description | Default values 198 | ---------|-----------------------------------------------------------------|---------------------- 199 | ngin | Path to directory where *.nuspec* to create package from it. | 200 | ngout | Optional path to save the final `.nupkg` package in other place.| 201 | wpath | *1.4+* To change working directory. | 1.4+ *(The absolute path of the directory where the GetNuTool is located)* 202 | 203 | ```bat 204 | gnt /t:pack /p:ngin=path\to\dir 205 | gnt /t:pack /p:ngin="path to\dir";ngout=..\dst.nupkg 206 | ``` 207 | 208 | ## Global Properties 209 | 210 | Property | Value 211 | ---------|------------- 212 | debug | `true` to add extra info in stream. 213 | logo | `no` to hide logo when processing starts. 214 | 215 | For example: 216 | 217 | ```bat 218 | gnt /t:pack /p:ngin=packages\LX4Cnh /p:debug=true 219 | ``` 220 | 221 | ```bat 222 | set debug=true & gnt /p:ngpackages="Conari;LX4cn;Fnv1a128";break=no 223 | ``` 224 | 225 | ## Extra Editions 226 | 227 | ### Compiled. SobaScript component 228 | 229 | GetNuTool now is part of [NuGetComponent](https://3F.github.io/web.vsSBE/doc/Scripts/SBE-Scripts/Components/NuGetComponent/) 230 | 231 | ```java 232 | #[NuGet gnt.raw("/t:pack /p:ngin=D:\7z.Libs")] 233 | ``` 234 | 235 | ### C# GetNuTool.cs 236 | 237 | GetNuTool.cs includes a fully compatible *gnt.core* inside. 238 | 239 | Add GetNuTool.cs to your project (.NET Framework 4.0+, .NET 5+, Mono, .NET Core, .NET Standard), then command like: 240 | 241 | ```csharp 242 | var gnt = new net.r_eg.GetNuTool(); 243 | gnt.Run(ngpackages: "Conari;regXwild"); 244 | ... 245 | gnt.Run(ngpackages: "Fnv1a128"); 246 | ``` 247 | 248 | ### Batch (.bat) version 249 | 250 | ~8 KB `gnt.bat` includes a fully compatible *gnt.core* inside. 251 | 252 | #### gnt.bat extra arguments 253 | 254 | First key to gnt.bat | Description | Example 255 | ----------------------|-------------------------------------------------------------------------------|---------------- 256 | ... | 1.9+ alias to `ngpackages=...` | `gnt Conari`, `gnt "regXwild;Fnv1a128"` 257 | `-unpack` | 1.6+ To generate minified gnt.core from gnt.bat. | `gnt -unpack` 258 | ~~`-msbuild`~~ path | 1.6 - 1.8 To use specific msbuild. Removed in 1.9. Override engine instead | `gnt -msbuild "D:\MSBuild\bin\amd64\msbuild" /p:ngpackages=Conari` 259 | 260 | #### Override engine 261 | 262 | Since the `-msbuild` key was removed in 1.9 as obsolete, you have following ways to override engine search: 263 | 264 | Either create `msb.gnt.cmd` in the directory from which the call *gnt.bat* is planned; with the following content, for example: 265 | 266 | ```bat 267 | @echo msbuild.exe 268 | ``` 269 | 270 | Or place a full version of [hMSBuild.bat](https://github.com/3F/hMSBuild) (~19 KB) tool instead of *msb.gnt.cmd* stub. 271 | 272 | 273 | Or -unpack command: 274 | 275 | ```bat 276 | gnt -unpack & msbuild.exe gnt.core {args} 277 | ``` 278 | 279 | Or `msb.gnt.cmd` environment variable: 280 | 281 | ```bat 282 | set msb.gnt.cmd=msbuild.exe & gnt {args} 283 | ``` 284 | 285 | ## Examples 286 | 287 | ```bat 288 | gnt vsSolutionBuildEvent/1.16.1:../SDK & SDK\GUI 289 | ``` 290 | 291 | ```bat 292 | gnt Conari 293 | gnt /p:ngpackages=Conari 294 | msbuild gnt.core /p:ngpackages=Conari 295 | ``` 296 | 297 | ```bat 298 | gnt "Conari;regXwild;MvsSln" 299 | gnt /p:ngpackages="Conari;regXwild;MvsSln" 300 | ``` 301 | 302 | ```bat 303 | gnt Fnv1a128 304 | gnt /t:pack /p:ngin=packages/Fnv1a128 305 | ``` 306 | 307 | ```bat 308 | msbuild gnt.core /p:ngconfig=".nuget/packages.config";ngpath="../packages" 309 | ``` 310 | 311 | ```bat 312 | gnt Conari /p:proxycfg="guest:1234@10.0.2.15:7428" 313 | ``` 314 | 315 | ```bat 316 | set ngpackages=Conari & call gnt || echo Failed 317 | ``` 318 | 319 | ```bat 320 | gnt "7z.Libs;vsSolutionBuildEvent/1.16.1:../packages/SDK" 321 | ``` 322 | 323 | Direct link to a remote package via https: 324 | 325 | ```bat 326 | gnt :DllExport /p:ngserver=https://server/DllExport.1.7.4.nupkg 327 | ``` 328 | 329 | Direct link to a local package that will be stored at the top level next to the *gnt* 330 | 331 | ```bat 332 | gnt : /p:ngserver=D:/local_dir/vsSolutionBuildEvent.SDK10.nupkg /p:ngpath=SDK10 333 | ``` 334 | 335 | ```bat 336 | gnt "Conari;Fnv1a12;LX4Cnh" /p:break=no /p:debug=true 337 | 338 | Conari use D:\prg\projects\GetNuTool\GetNuTool\bin\Release\packages\Conari 339 | Fnv1a12 ... The remote server returned an error: (404) Not Found. 340 | LX4Cnh ... D:\prg\projects\GetNuTool\GetNuTool\bin\Release\packages\LX4Cnh 341 | - /.version 342 | - /build-info.txt 343 | - /lib/net40/LX4Cnh.dll 344 | - /lib/net40/LX4Cnh.xml 345 | - /lib/net5.0/LX4Cnh.dll 346 | - /lib/net5.0/LX4Cnh.xml 347 | - /License.txt 348 | - /LX4Cnh.nuspec 349 | - /Readme.md 350 | - /tools/gnt.bat 351 | - /tools/hMSBuild.bat 352 | ... 353 | ``` 354 | 355 | ```bat 356 | gnt Huid/1.0.0:src.zip /t:grab 357 | ``` 358 | 359 | See also examples from [tests/](tests/keysAndLogicTests.bat) 360 | 361 | ### Build and Use from source 362 | 363 | ```bat 364 | git clone https://github.com/3F/GetNuTool.git src 365 | cd src & build & bin\Release\gnt Conari 366 | ``` 367 | 368 | ### .sha1 official distribution 369 | 370 | *GetNuTool* releases are now accompanied by a *.sha1* file in the official distribution; At the same time, commits from which releases are published are signed with the committer's verified signature (GPG). 371 | 372 | Make sure you are using official, unmodified, safe versions. 373 | 374 | Note: *.sha1* file is a text list of published files with checksums in the format: 375 | 376 | `40-hexadecimal-digits` `` `file` 377 | 378 | ``` 379 | eead8f5c1fdff2abd4da7d799fbbe694d392c792 path\file 380 | ... 381 | ``` 382 | 383 | ## Contributing 384 | 385 | [*GetNuTool*](https://github.com/3F/GetNuTool) is waiting for your awesome contributions! -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | :: max 2047 or 8191 (XP+) characters 4 | set /a packmaxline=1940 5 | 6 | call .tools\hMSBuild -GetNuTool & if [%~1]==[#] exit /B 0 7 | 8 | set "reltype=%~1" & if not defined reltype set reltype=Release 9 | call packages\vsSolutionBuildEvent\cim.cmd ~x ~c %reltype% || goto err 10 | 11 | setlocal enableDelayedExpansion 12 | cd tests 13 | call a initAppVersion Gnt 14 | call a execute ..\obj\gnt & call a msgOrFailAt 1 "GetNuTool %appversionGnt%" || goto err 15 | call a printMsgAt 1 3F "Completed as a " 16 | endlocal 17 | exit /B 0 18 | 19 | :err 20 | echo Failed build>&2 21 | exit /B 1 -------------------------------------------------------------------------------- /caller.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | ::! GetNuTool /wrapper/batch edition 3 | ::! Copyright (c) 2015-2024 Denis Kuzmin github/3F 4 | ::! https://github.com/3F/GetNuTool 5 | 6 | set gntcore=gnt.core 7 | if not exist %gntcore% goto error 8 | 9 | set /a ERROR_FILE_NOT_FOUND=2 10 | set /a ERROR_CALL_NOT_IMPLEMENTED=120 11 | 12 | :: Syntax: 13 | :: gnt Package 14 | :: gnt "Paclage1;Package2" 15 | :: gnt 16 | :: gnt 17 | 18 | if "%~1"=="-unpack" goto off 19 | 20 | set args=%* 21 | setlocal enableDelayedExpansion 22 | 23 | :: +1 space because %first:~0,1% will return literally "~0,1" as value if it's empty 24 | set "first=%~1 " 25 | set key=!first:~0,1! 26 | if "!key!" NEQ " " if !key! NEQ / set args=/p:ngpackages=!args! 27 | 28 | set "instance=%msb.gnt.cmd%" 29 | if defined instance goto found 30 | 31 | :: Find engine via msb.gnt.cmd stub or hMSBuild.bat script https://github.com/3F/hMSBuild 32 | 33 | set script=hMSBuild 34 | if exist msb.gnt.cmd set script=msb.gnt.cmd 35 | 36 | for /F "tokens=*" %%i in ('%script% -only-path 2^>^&1 ^&call echo %%^^ERRORLEVEL%%') do 2>nul ( 37 | if not defined instance ( set instance="%%i" ) else set EXIT_CODE=%%i 38 | ) 39 | 40 | if .%EXIT_CODE%==.0 if exist !instance! goto found 41 | 42 | :: Find engine via system records 43 | 44 | for %%v in (4.0, 14.0, 12.0, 3.5, 2.0) do ( 45 | for /F "usebackq tokens=2* skip=2" %%a in ( 46 | `reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\%%v" /v MSBuildToolsPath 2^> nul` 47 | ) do if exist %%b ( 48 | 49 | set instance="%%~b\MSBuild.exe" 50 | if exist !instance! ( 51 | 52 | if %%v NEQ 3.5 if %%v NEQ 2.0 goto found 53 | 54 | echo Override engine or contact for legacy support %%v 55 | exit /B %ERROR_CALL_NOT_IMPLEMENTED% 56 | ) 57 | ) 58 | ) 59 | 60 | :error 61 | echo Engine or %gntcore% is not found. >&2 62 | echo Try the full version or call it manually: msbuild %gntcore% ... >&2 63 | exit /B %ERROR_FILE_NOT_FOUND% 64 | 65 | :off 66 | echo This feature is disabled in current version >&2 67 | exit /B %ERROR_CALL_NOT_IMPLEMENTED% 68 | 69 | :found 70 | set con=/noconlog 71 | if "%debug%"=="true" set con=/v:q 72 | 73 | call :unset "/help" "-help" "/h" "-h" "/?" "-?" 74 | 75 | call !instance! %gntcore% /nologo /noautorsp !con! /p:wpath="%cd%/" !args! 76 | exit /B !ERRORLEVEL! 77 | 78 | :unset 79 | if defined args set args=!args:%~1=! 80 | if "%~2" NEQ "" shift & goto unset 81 | exit /B 0 -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- 1 | - - - - - - - - - - - - - - - - - - - - - 2 | GetNuTool - https://github.com/3F/GetNuTool 3 | - - - - - - - - - - - - - - - - - - - - - 4 | 5 | [1.9] 2024.02.07 6 | 7 | * FIXED: TLS 1.3 (and newer versions) support. 8 | 9 | * FIXED: Invalid return code in gnt.bat in attempt to use `||` 10 | 11 | * FIXED: Incorrect delayed expansion when embedding gnt.bat 12 | 13 | * NEW: Added `break` option to control the break on first package error when multiple receiving. 14 | 15 | * NEW: Hash values control using `sha1` for receiving every package if used unsecured channels (~windows xp) etc. 16 | `get` & `grab` modes; packages.config & inline records support. 17 | 18 | * NEW: Implemented alias to `ngpackages=...` gnt.bat. 19 | ``` 20 | gnt Conari 21 | gnt "regXwild;Fnv1a128" 22 | ``` 23 | 24 | * NEW: Added new `grab` mode. Grabs data without unpacking. The available parameters are similar to `get`. 25 | ``` 26 | gnt Huid/1.0.0:src.nupkg /t:grab 27 | gnt :../netfx4sdk.cmd /t:grab /p:ngserver=https://server/netfx4sdk.cmd 28 | ``` 29 | 30 | * NEW: `ssl3=true` option to not drop legacy ssl3, tls1.0, tls1.1. 31 | 32 | * NEW: Added `logo` global property to hide logo when processing starts. 33 | 34 | * NEW: Extra C# edition: GetNuTool.cs includes a fully compatible gnt.core inside. 35 | (.NET Framework 4.0+, .NET 5+, Mono, .NET Core, .NET Standard) 36 | ``` 37 | var gnt = new net.r_eg.GetNuTool(); 38 | gnt.Run(ngpackages: "Conari;regXwild"); 39 | ... 40 | gnt.Run(ngpackages: "Fnv1a128"); 41 | ``` 42 | 43 | * CHANGED: ngconfig default values: packages.config;.tools\packages.config 44 | 45 | * CHANGED: Removed `-msbuild` key in gnt.bat. Override engine instead. 46 | 47 | * CHANGED: Overriding engine in gnt.bat via msb.gnt.cmd (either file or environment variable) 48 | 49 | * CHANGED: Dropped support for ssl3 + tls1.0 + tls1.1 by default. 50 | Set `ssl3=true` to cancel this. 51 | 52 | * NOTE: GetNuTool releases are now accompanied by a .sha1 file in the official distribution; 53 | At the same time, commits from which releases are published are signed with the committer's verified signature (GPG). 54 | 55 | Make sure you are using official, unmodified, safe versions. 56 | https://github.com/3F/GetNuTool/releases/latest 57 | 58 | 59 | [1.8] 2020.01.16 60 | 61 | * CHANGED: Changed `%~dp0` to `%cd%` processing for the following in batch version by default: 62 | 63 | `wpath` property 64 | `-unpack` key 65 | 66 | For some cases you need to update the use of the batch version in your code. 67 | Do not hesitate to contact if you have the questions: 68 | https://github.com/3F/GetNuTool 69 | 70 | * CHANGED: Trims whitespaces in optional proxycfg property. 71 | 72 | Helps to avoid MSB1006 problem for 3rd tools which was based on gnt batch version. 73 | That is, 74 | 75 | ~ /p:proxycfg=" !proxy! " will be safely considered as optional value 76 | While /p:proxycfg="" will indicate about incorrect or missing data. 77 | 78 | * FIXED: Fixed post actions when executing gnt core in batch version. 79 | 80 | * FIXED: "The remote server returned an error: (407) Proxy Authentication Required." 81 | 82 | Related issue: https://github.com/3F/DllExport/issues/133 83 | 84 | * NOTE: Official releases via GitHub Releases: 85 | https://github.com/3F/GetNuTool/releases/latest 86 | 87 | * NOTE: About possible commands and keys: https://github.com/3F/GetNuTool#commands 88 | 89 | 90 | [v1.7] 2018.12.22 91 | 92 | * NEW: New logic to specify multiple packages and config files via delimiters. 93 | Now main core just ignores `;` when `|` is found. 94 | https://github.com/3F/GetNuTool/issues/7#issuecomment-445486968 95 | 96 | Read the documentation. 97 | 98 | * FIXED: Fixed problems with special symbols in path. Issue #7 99 | ``` 100 | ' &!~`@#$^(+)_=%-;[.]{,} 101 | ``` 102 | 103 | * CHANGED: Batch version now uses safe logic for work with special symbols from `-msbuild` key. 104 | * CHANGED: Fully updated compression for generating more lightweight distribution. 105 | Useful for projects like DllExport, hMSBuild, and so on. 106 | 107 | New way for argument passing into the main core. 108 | 109 | 110 | [1.6.2] 2018.08.05 111 | 112 | * FIXED: Bug when the output path for packages may contain `:` 113 | e.g. like absolute path from %cd% ~ D:\path\... 114 | 115 | * FIXED: Possible 'The request was aborted: Could not create SSL/TLS secure channel.' 116 | Related issue: https://github.com/3F/DllExport/issues/77#issuecomment-405055379 117 | 118 | * NEW: Implemented proxy support via `$(proxycfg)`. Issue #5 119 | 120 | [1.6.1] 2017.08.18 121 | 122 | * FIXED: Fixed problem "Input string was not in a correct format" when used version with release type, 123 | e.g.: 1.2.3-alpha, 1.2.3-beta-2, 1.2.3-rc ... 124 | 125 | * FIXED: Avoids errors with possible incorrect CRC & Compressed size info. Issue #3 126 | * FIXED: Fixed problems with paths and whitespace characters for `-unpack` command in executable version. 127 | * CHANGED: Removed '15.0' from searching by registry key as an unused way for all new VS2017+ 128 | * CHANGED: 'MSBuild was not found' now returns (0x2) ERROR_FILE_NOT_FOUND 129 | * CHANGED: Changed variable name %msbuild% to %msbuildexe% that was related for Issue #2 130 | * CHANGED: Improved comparing arguments for executable version. 131 | 132 | [1.6] 2016.12.08 133 | 134 | * NEW: Executable version. Implemented `-unpack` command. 135 | To generate minified version from executable. 136 | ``` 137 | gnt -unpack 138 | ``` 139 | 140 | * NEW: Executable version. Implemented `-msbuild` command. 141 | To use specific msbuild for executable version. 142 | ``` 143 | gnt -msbuild "D:\MSBuild\bin\amd64\msbuild" /p:ngpackages="Conari" 144 | ``` 145 | 146 | * NEW: Added ';' splitter for .config files. 147 | The `|` now is marked as obsolete and can be removed in new versions. 148 | 149 | * NEW: MSBuild-helper with `-notamd64` option. 150 | Related issue: https://github.com/3F/vsSolutionBuildEvent/issues/38 151 | 152 | * FIXED: Part of unhandled exceptions has been changed on messages to stderr: 153 | `The "PrepareList" task failed unexpectedly / FileNotFoundException` 154 | The "NGPack" task - DirectoryNotFoundException & The "NGDownload" task - WebException 404 155 | 156 | * CHANGED: Value of `ngconfig` property now is `packages.config` by default. 157 | 158 | [1.5] 159 | 160 | * FIXED: error MSB4018 `Value cannot be null`, if the `/p:wpath` key is not defined. 161 | 162 | [1.4] 163 | 164 | * NEW: Added `/p:wpath` key to define working directory. 165 | * NEW: Support of executable package. 166 | * NEW: MSBuild searcher. 167 | 168 | [1.3] 169 | 170 | * NEW: Added `/p:debug` to display additional information from selected command. 171 | * CHANGED: Compact output for processed files. 172 | * CHANGED: CA2202 -> sout 173 | 174 | [1.2] 175 | 176 | * NEW: Packing packages into .nupkg by using .nuspec 177 | * CHANGED: The `get` & `pack` commands for calling of main features. 178 | * CHANGED: Attributes of packages.config is now are case sensitive. Use lowercase for `id`, `version`, `output` 179 | * CHANGED: For `get` command: ignoring technical data from package like: /_rels, /package, etc. 180 | 181 | [1.1] 182 | 183 | * FIXED: Incorrect path to Microsoft.Build.Tasks.dll with new MSBuild 14.0 184 | * NEW: Compact version - `gnt-compact.core` 185 | * CHANGED: Ignoring downloading if this folder is already exists. Remove folder to avoid restriction. 186 | 187 | [1.0] 188 | 189 | * The first point - lightweight non-binary tool for getting the NuGet packages via MSBuild Tool 190 | 191 | 192 | -------------------------------------------------------------------------------- /csharp.cs: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright (c) 2015 Denis Kuzmin github/3F 3 | * Copyright (c) GetNuTool contributors https://github.com/3F/GetNuTool/graphs/contributors 4 | * Licensed under the MIT License (MIT). 5 | * See accompanying LICENSE file or visit https://github.com/3F/GetNuTool 6 | */ 7 | 8 | // TODO: This was part of logic.targets separated between Tasks. New structure needs to be reviewed! 9 | 10 | // NOTE: netfx 4.0+ platforms; 11 | // NOTE: The default console logger can be disabled and currently exceptions are not caught at the top level; To make the code compact, use `return false` instead 12 | 13 | if("$(logo)" != "no") Console.WriteLine("\nGetNuTool $(GetNuTool)\n(c) 2015-2024 Denis Kuzmin github/3F\n"); 14 | 15 | const string MSG_NOTFOUND = "{0} is not found "; 16 | 17 | var ignore = new string[] // to ignore from package 18 | { 19 | "/_rels/", 20 | "/package/", 21 | "/[Content_Types].xml" 22 | }; 23 | 24 | Action DebugMessage = (msg, args) => 25 | { 26 | if("$(debug)".Trim() == "true") Console.WriteLine(msg, args); 27 | }; 28 | 29 | Func _LoadXml = (input) => 30 | { 31 | try 32 | { 33 | return XDocument.Load(input).Root; 34 | } 35 | catch(Exception ex) 36 | { 37 | Console.Error.WriteLine(ex.Message); 38 | throw; 39 | } 40 | }; 41 | 42 | Func _FormatList = (str) => str.Split 43 | ( 44 | new[] { str.Contains('|') ? '|' : ';' }, 45 | StringSplitOptions.RemoveEmptyEntries 46 | ); 47 | 48 | if(tmode == "get" || tmode == "grab") 49 | { 50 | string plist = @"$(ngpackages)"; 51 | 52 | var sb = new StringBuilder(); 53 | 54 | if(string.IsNullOrEmpty(plist)) 55 | { 56 | Action LoadConf = (cfg) => 57 | { 58 | foreach(XElement pkg in _LoadXml(cfg).Descendants("package")) 59 | { 60 | XAttribute id = pkg.Attribute("id"); 61 | XAttribute version = pkg.Attribute("version"); 62 | XAttribute output = pkg.Attribute("output"); 63 | XAttribute sha1 = pkg.Attribute("sha1"); 64 | 65 | if(id == null) 66 | { 67 | Console.Error.WriteLine("{0} is corrupted", cfg); 68 | return; 69 | } 70 | 71 | sb.Append(id.Value); 72 | 73 | if(version != null) sb.Append("/" + version.Value); 74 | if(sha1 != null) sb.Append("?" + sha1.Value); 75 | if(output != null) sb.Append(":" + output.Value); 76 | 77 | sb.Append(';'); 78 | } 79 | }; 80 | 81 | foreach(string cfg in _FormatList(@"$(ngconfig)")) 82 | { 83 | string lcfg = Path.Combine(@"$(wpath)", cfg); 84 | 85 | if(File.Exists(lcfg)) 86 | { 87 | LoadConf(lcfg); 88 | } 89 | else DebugMessage(MSG_NOTFOUND, lcfg); 90 | } 91 | 92 | if(sb.Length < 1) 93 | { 94 | Console.Error.WriteLine("Empty .config + ngpackages"); 95 | return false; 96 | } 97 | 98 | plist = sb.ToString(); 99 | } 100 | 101 | /* -_-_-_--_-_-_--_-_-_- */ 102 | 103 | string defpath =@"$(ngpath)"; 104 | string proxy =@"$(proxycfg)"; 105 | 106 | // https://github.com/3F/DllExport/issues/140 107 | // Since Tls13 (0x3000) is not available from obsolete assemblies, 108 | // and SecurityProtocolType.SystemDefault (0) is defined only for netfx 4.7+, 4.8; 109 | // We can try to bind this at runtime using the last available environment where this code was executed. 110 | 111 | // NOTE: ServicePointManager.SecurityProtocol = 0 may produce the following problem: An unexpected error occurred on a receive. 112 | 113 | foreach(var s in Enum.GetValues(typeof(SecurityProtocolType)).Cast()) 114 | { 115 | try 116 | { 117 | ServicePointManager.SecurityProtocol |= s; 118 | } 119 | catch(NotSupportedException) 120 | { 121 | // we don't care because property `ssl3` controls legacy protocols 122 | } 123 | } 124 | 125 | // drop support for ssl3 + tls1.0 + tls1.1 126 | // https://learn.microsoft.com/en-us/dotnet/api/system.net.securityprotocoltype 127 | if("$(ssl3)" != "true") 128 | ServicePointManager.SecurityProtocol &= 129 | ~(SecurityProtocolType)(/*Ssl3*/48 | /*Tls*/192 | /*Tls11*/768); 130 | 131 | Func GetProxy = (cfg) => 132 | { 133 | var auth = cfg.Split('@'); 134 | if(auth.Length <= 1) return new WebProxy(auth[0], false); 135 | 136 | var login = auth[0].Split(':'); 137 | return new WebProxy(auth[1], false) 138 | { 139 | Credentials = new NetworkCredential 140 | ( 141 | login[0], 142 | login.Length > 1 ? login[1] : null 143 | ) 144 | }; 145 | }; 146 | 147 | Func SetDir = (path) => 148 | { 149 | string dir = Path.GetDirectoryName(path); 150 | if(!Directory.Exists(dir)) Directory.CreateDirectory(dir); 151 | return path; 152 | }; 153 | 154 | Func GetLink = (link, name, path, sha1) => 155 | { 156 | string to = Path.GetFullPath 157 | ( 158 | Path.Combine(@"$(wpath)", path ?? name ?? string.Empty) 159 | ); 160 | 161 | if(Directory.Exists(to) || File.Exists(to)) 162 | { 163 | Console.WriteLine("{0} use {1}", name, to); 164 | return true; 165 | } 166 | 167 | Console.Write(link + " ... "); 168 | 169 | bool grab = tmode == "grab"; 170 | 171 | string tmp = grab 172 | ? SetDir(to) 173 | : Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); 174 | 175 | using(var l = new WebClient()) 176 | { 177 | try 178 | { 179 | if(!string.IsNullOrEmpty(proxy)) 180 | { 181 | l.Proxy = GetProxy(proxy); 182 | } 183 | 184 | l.Headers.Add("User-Agent", "GetNuTool/$(GetNuTool)"); 185 | l.UseDefaultCredentials = true; 186 | 187 | // `WebClient.Credentials` will not affect for used proxy: https://github.com/3F/DllExport/issues/133 188 | if(l.Proxy != null && l.Proxy.Credentials == null) // when no proxy key or when GetProxy() uses auth[0] 189 | { 190 | l.Proxy.Credentials = CredentialCache.DefaultCredentials; 191 | } 192 | 193 | l.DownloadFile(@"$(ngserver)" + link, tmp); 194 | } 195 | catch(Exception ex) 196 | { 197 | Console.Error.WriteLine(ex.Message); 198 | return false; 199 | } 200 | } 201 | 202 | Console.WriteLine(to); 203 | 204 | if(sha1 != null) 205 | { 206 | Console.Write("{0} ... ", sha1); 207 | using(SHA1 algo = System.Security.Cryptography.SHA1.Create()) 208 | { 209 | sb.Clear(); 210 | 211 | using(var stream = new FileStream(tmp, FileMode.Open, FileAccess.Read)) 212 | foreach(byte b in algo.ComputeHash(stream)) 213 | sb.Append(b.ToString("x2")); 214 | 215 | Console.Write(sb.ToString()); 216 | if(!sb.ToString().Equals(sha1, StringComparison.OrdinalIgnoreCase)) 217 | { 218 | Console.WriteLine("[x]"); 219 | return false; 220 | } 221 | Console.WriteLine(); 222 | } 223 | } 224 | 225 | if(grab) return true; 226 | 227 | using(Package pkg = ZipPackage.Open(tmp, FileMode.Open, FileAccess.Read)) 228 | { 229 | foreach(PackagePartCollection part in pkg.GetParts()) 230 | { 231 | string uri = Uri.UnescapeDataString(part.Uri.OriginalString); 232 | if(ignore.Any(x => uri.StartsWith(x, StringComparison.Ordinal))) continue; 233 | 234 | string dest = Path.Combine(to, uri.TrimStart('/')); 235 | DebugMessage("- {0}", uri); 236 | 237 | using(Stream src = part.GetStream(FileMode.Open, FileAccess.Read)) 238 | using(FileStream target = File.OpenWrite(SetDir(dest))) 239 | { 240 | try 241 | { 242 | src.CopyTo(target); 243 | } 244 | catch(FileFormatException) { DebugMessage("[x]?crc: {0}", dest); } 245 | } 246 | } 247 | } 248 | File.Delete(tmp); 249 | return true; 250 | }; 251 | 252 | //Format: id[/version][?sha1][:path];id2[/version][?sha1][:path];... 253 | 254 | foreach(string pkg in _FormatList(plist)) 255 | { 256 | string[] ident = pkg.Split(new[] { ':' }, 2); 257 | string[] link = ident[0].Split(new[] { '?' }, 2); 258 | string path = ident.Length > 1 ? ident[1] : null; 259 | string name = link[0].Replace('/', '.'); 260 | 261 | if(!string.IsNullOrEmpty(defpath)) 262 | { 263 | path = Path.Combine(defpath, path ?? name); 264 | } 265 | 266 | if(!GetLink(link[0], name, path, /*sha1:*/ link.Length > 1 ? link[1] : null) 267 | && "$(break)".Trim() != "no") return false; 268 | } 269 | } 270 | else if(tmode == "pack") 271 | { 272 | const string EXT_NUSPEC = ".nuspec"; 273 | const string TAG_META = "metadata"; 274 | 275 | // Tags 276 | const string ID = "id"; 277 | const string VER = "version"; 278 | 279 | string dir = Path.Combine(@"$(wpath)", @"$(ngin)"); 280 | if(!Directory.Exists(dir)) 281 | { 282 | Console.Error.WriteLine(MSG_NOTFOUND, dir); 283 | return false; 284 | } 285 | 286 | // Get metadata 287 | 288 | string nuspec = Directory.GetFiles(dir, "*" + EXT_NUSPEC).FirstOrDefault(); 289 | if(nuspec == null) 290 | { 291 | Console.Error.WriteLine(MSG_NOTFOUND + dir, EXT_NUSPEC); 292 | return false; 293 | } 294 | Console.WriteLine("{0} use {1}", EXT_NUSPEC, nuspec); 295 | 296 | XElement root = _LoadXml(nuspec).Elements().FirstOrDefault(x => x.Name.LocalName == TAG_META); 297 | if(root == null) 298 | { 299 | Console.Error.WriteLine(MSG_NOTFOUND, TAG_META); 300 | return false; 301 | } 302 | 303 | var metadata = new System.Collections.Generic.Dictionary(); 304 | 305 | Func _GetMeta = (key) 306 | => metadata.ContainsKey(key) ? metadata[key] : string.Empty; 307 | 308 | foreach(XElement tag in root.Elements()) 309 | metadata[tag.Name.LocalName.ToLower()] = tag.Value; 310 | 311 | // Validate id; nuget core based rule 312 | 313 | if(_GetMeta(ID).Length > 100 314 | || !System.Text.RegularExpressions.Regex.IsMatch 315 | ( 316 | _GetMeta(ID), 317 | @"^\w+(?:[_.-]\w+)*$" 318 | )) 319 | { 320 | Console.Error.WriteLine("Invalid id"); 321 | return false; 322 | } 323 | 324 | // Format package 325 | 326 | string pout = string.Format("{0}.{1}.nupkg", _GetMeta(ID), _GetMeta(VER)); 327 | 328 | string dout = Path.Combine(@"$(wpath)", @"$(ngout)"); 329 | if(!string.IsNullOrWhiteSpace(dout)) 330 | { 331 | if(!Directory.Exists(dout)) 332 | { 333 | Directory.CreateDirectory(dout); 334 | } 335 | pout = Path.Combine(dout, pout); 336 | } 337 | 338 | Console.WriteLine("Creating package {0} ...", pout); 339 | using(string pkg = Package.Open(pout, FileMode.Create)) 340 | { 341 | // manifest relationship 342 | 343 | Uri manifestUri = new Uri(string.Format("/{0}{1}", _GetMeta(ID), EXT_NUSPEC), UriKind.Relative); 344 | pkg.CreateRelationship(manifestUri, TargetMode.Internal, "http://schemas.microsoft.com/packaging/2010/07/manifest"); 345 | 346 | // content 347 | 348 | foreach(string file in Directory.GetFiles(dir, "*.*", SearchOption.AllDirectories)) 349 | { 350 | if(ignore.Any(x => file.StartsWith 351 | ( 352 | Path.Combine(dir, x.Trim('/')), StringComparison.Ordinal 353 | ))) continue; 354 | 355 | string pUri = file.StartsWith(dir, StringComparison.OrdinalIgnoreCase) 356 | ? file.Substring(dir.Length).TrimStart(Path.DirectorySeparatorChar) 357 | : file; 358 | 359 | DebugMessage("+ {0}", pUri); 360 | 361 | PackagePart part = pkg.CreatePart 362 | ( 363 | // to protect path without separators 364 | PackUriHelper.CreatePartUri 365 | ( 366 | new Uri 367 | ( 368 | string.Join("/", pUri.Split('\\', '/').Select(Uri.EscapeDataString)), 369 | UriKind.Relative 370 | ) 371 | ), 372 | "application/octet", //DEF_CONTENT_TYPE: System.Net.Mime.MediaTypeNames.Application.Octet 373 | CompressionOption.Maximum 374 | ); 375 | 376 | using (Stream tstream = part.GetStream()) 377 | using(var fs = new FileStream(file, FileMode.Open, FileAccess.Read)) { 378 | fs.CopyTo(tstream); 379 | } 380 | } 381 | 382 | // metadata 383 | 384 | PackageProperties _p = pkg.PackageProperties; 385 | 386 | _p.Creator = _GetMeta("authors"); 387 | _p.Description = _GetMeta("description"); 388 | _p.Identifier = _GetMeta(ID); 389 | _p.Version = _GetMeta(VER); 390 | _p.Keywords = _GetMeta("tags"); 391 | _p.Title = _GetMeta("title"); 392 | _p.LastModifiedBy = "GetNuTool/$(GetNuTool)"; 393 | } 394 | } 395 | 396 | else return false; -------------------------------------------------------------------------------- /csinit.targets: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 15 | 16 | packages.config;.tools\packages.config 17 | https://www.nuget.org/api/v2/package/ 18 | packages 19 | 20 | x 21 | $(MSBuildProjectDirectory) 22 | 23 | $(MSBuildToolsPath)\Microsoft.Build.Tasks.v$(MSBuildToolsVersion).dll 24 | $(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll 25 | 26 | 27 | 28 |
29 | 30 | 31 |
32 | 33 | 34 |
35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /demo.vssbe.bat: -------------------------------------------------------------------------------- 1 | @call :GetNuTool vsSolutionBuildEvent/%v% || ( echo Please contact support>&2 & exit /B1 ) 2 | if "%~1"=="" packages\vsSolutionBuildEvent.%v%\GUI 3 | :GetNuTool 4 | -------------------------------------------------------------------------------- /demo/vsSolutionBuildEvent.bat: -------------------------------------------------------------------------------- 1 | @call :GetNuTool vsSolutionBuildEvent || ( echo Please contact support>&2 & exit /B1 ) 2 | if "%~1"=="" packages\vsSolutionBuildEvent\GUI 3 | :GetNuTool 4 | @echo off 5 | ::! GetNuTool /shell/batch edition 6 | ::! Copyright (c) 2015-2024 Denis Kuzmin github/3F 7 | ::! https://github.com/3F/GetNuTool 8 | set ee=gnt.core&set ef="%temp%\%ee%1.9.0%random%%random%"&if "%~1"=="-unpack" goto en 9 | if "%~1"=="-msbuild" goto eo 10 | set eg=%*&setlocal enableDelayedExpansion&set "eh=%~1 "&set ei=!eh:~0,1!&if "!ei!" NEQ " " if !ei! NEQ / set eg=/p:ngpackages=!eg! 11 | set "ej=%msb.gnt.cmd%"&if defined ej goto ep 12 | set ek=hMSBuild&if exist msb.gnt.cmd set ek=msb.gnt.cmd 13 | for /F "tokens=*" %%i in ('%ek% -only-path 2^>^&1 ^&call echo %%^^ERRORLEVEL%%') do 2>nul (if not defined ej (set ej="%%i")else set el=%%i) 14 | if .%el%==.0 if exist !ej! goto ep 15 | for %%v in (4.0,14.0,12.0,3.5,2.0)do (for /F "usebackq tokens=2* skip=2" %%a in (`reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\%%v" /v MSBuildToolsPath 2^> nul`) do if exist %%b (set ej="%%~b\MSBuild.exe" 16 | if exist !ej! (if %%v NEQ 3.5 if %%v NEQ 2.0 goto ep 17 | echo Override engine or contact for legacy support %%v&exit/B120)))&echo Engine is not found. Try with hMSBuild 1>&2 18 | exit/B2 19 | :eo 20 | echo This feature is disabled in current version >&2 21 | exit/B120 22 | :ep 23 | set em=/noconlog&if "%debug%"=="true" set em=/v:q 24 | call :eq&call :er "/help" "-help" "/h" "-h" "/?" "-?"&call !ej! %ef% /nologo /noautorsp !em! /p:wpath="%cd%/" !eg!&set el=!ERRORLEVEL!&del /Q/F %ef%&exit/B!el! 25 | :en 26 | set ef="%cd%\%ee%"&echo Generating a %ee% at %cd%\... 27 | :eq 28 | setlocal disableDelayedExpansion 29 | %ef%&set -=ngconfig&set [=Condition&set ]=packages.config&set ;=ngserver&set .=package&set ,=GetNuTool&set :=wpath&set +=TaskCoreDllPath&set {=Exists&set }=MSBuildToolsPath&set _=Microsoft.Build.Tasks.&set a=MSBuildToolsVersion&set b=Target&set c=tmode&set d=ParameterGroup&set e=Reference&set f=System&set g=Namespace&set h=Console.WriteLine(&set i=string&set j=return&set k=Console.Error.WriteLine(&set l=string.IsNullOrEmpty(&set m=foreach&set n=Attribute&set o=Append&set p=Path&set q=Combine&set r=Length&set s=false&set t=ToString&set u=SecurityProtocolType&set v=ServicePointManager.SecurityProtocol&set w=Credentials&set x=Directory&set y=CreateDirectory&set z=Console.Write(&set $=using&set #=FileMode&set @=FileAccess&set `=StringComparison&set ?=StartsWith 30 | ^^^<%-% %[%="'$(%-%)'==''"^>%]%;.tools\%]%^^<%;% %[%="'$(%;%)'==''"^>https://www.nuget.org/api/v2/%.%/^^packages^^<%,%^>1.9.0^^<%:% %[%="'$(%:%)'==''"^>$(MSBuildProjectDirectory)^^<%+% %[%="%{%('$(%}%)\%_%v$(%a%).dll')"^>$(%}%)\%_%v$(%a%).dll^^<%+% %[%="'$(%+%)'=='' and %{%('$(%}%)\%_%Core.dll')"^>$(%}%)\%_%Core.dll^^^<%b% Name="get" BeforeTargets="Build"^>^^^<%b% Name="grab"^>^^^<%b% Name="pack"^>^^^^<%d%^>^<%c%/^>^^^<%e% Include="%f%.Xml"/^>^<%e% Include="%f%.Xml.Linq"/^>^<%e% Include="WindowsBase"/^>^^^^^^^^ github/3F\n");var d="{0} is not found ";var e=new %i%[]{"/_rels/","/%.%/","/[Content_Types].xml"};Action^<%i%,object^>f=(g,h)=^>{if("$(debug)".Trim()=="true")%h%g,h);};Func^<%i%,XElement^>i=j=^>{try{%j% XDocument.Load(j).Root;}catch(Exception k){%k%k.Message);throw;}};Func^<%i%,%i%[]^>l=m=^>m.Split(new[]{m.Contains('^|')?'^|':';'},(StringSplitOptions)1);if(%c%=="get"^|^|%c%=="grab"){var n=@"$(ngpackages)";var o=new StringBuilder();if(%l%n)){Action^<%i%^>p=q=^>{%m%(var r in i(q).Descendants("%.%")){var s=r.%n%("id");var t=r.%n%("version");var u=r.%n%("output");var v=r.%n%("sha1");if(s==null){%k%"{0} is corrupted",q);%j%;}o.%o%(s.Value);if(t!=null)o.%o%("/"+t.Value);if(v!=null)o.%o%("?"+v.Value);if(u!=null)o.%o%(":"+u.Value);o.%o%>>%ef% 31 | ()){try{%v%^|=z;}catch(NotSupportedException){}}if("$(ssl3)"!="true")%v%^&=~(%u%)(48^|192^|768);Func^<%i%,WebProxy^>D=q=^>{var E=q.Split('@');if(E.%r%^<=1)%j% new WebProxy(E[0],%s%);var F=E[0].Split(':');%j% new WebProxy(E[1],%s%){%w%=new NetworkCredential(F[0],F.%r%^>1?F[1]:null)};};Func^<%i%,%i%^>G=H=^>{var I=%p%.GetDirectoryName(H);if(!%x%.%{%(I))%x%.%y%(I);%j% H;};Func^<%i%,%i%,%i%,%i%,bool^>J=(K,L,H,v)=^>{var M=%p%.GetFullPath(%p%.%q%(@"$(%:%)",H??L??""));if(%x%.%{%(M)^|^|File.%{%(M)){%h%"{0} use {1}",L,M);%j% true;}%z%K+" ... ");var N=%c%=="grab";var O=N?G(M):%p%.%q%(%p%.GetTempPath(),Guid.NewGuid().%t%());%$%(var P=new WebClient()){try{if(!%l%y)){P.Proxy=D(y);}P.Headers.Add("User-Agent","%,%/$(%,%)");P.UseDefaultCredentials=true;if(P.Proxy!=null^&^&P.Proxy.%w%==null){P.Proxy.%w%=CredentialCache.DefaultCredentials;}P.DownloadFile(@"$(%;%)"+K,O);}catch(Exception k){%k%k.Message);%j% %s%;}}%h%M);if(v!=null){%z%"{0} ... ",v);%$%(var Q=%f%.Security.Cryptography.SHA1.Create()){o.Clear();%$%(var R=new FileStream(O,(%#%)3,(%@%)1))%m%(var S in Q.ComputeHash(R))o.%o%(S.%t%("x2"));%z%o.%t%());if(!o.%t%().Equals(v,(%`%)5)){%h%"[x]");%j% %s%;}%h%);}}if(N)%j% true;%$%(var r=ZipPackage.Open(O,(%#%)3,(%@%)1)){%m%(var T in r.GetParts()){var U=Uri.UnescapeDataString(T.Uri.OriginalString);if(e.Any(V=^>U.%?%(V,(%`%)4)))continue;var W=%p%.%q%(M,U.TrimStart('/'));f("- {0}",U);%$%(var X=T.GetStream((%#%)3,(%@%)1))%$%(var Y=File.OpenWrite(G(W))){try{X.CopyTo(Y);}catch(FileFormatException){f("[x]?crc: {0}",W);}}}}File.Delete(O);%j% true;};%m%(var r in l(n)){var Z=r.Split(new[]{':'},2);var K=Z[0].Split(new[]{'?'},2);var H=Z.%r%^>1?Z[1]:null;var L=K[0].Replace('/','.');if(!%l%>>%ef% 32 | 1?K[1]:null)^&^&"$(break)".Trim()!="no")%j% %s%;}}else if(%c%=="pack"){var a=".nuspec";var b="metadata";var c="id";var A="version";var I=%p%.%q%(@"$(%:%)",@"$(ngin)");if(!%x%.%{%(I)){%k%d,I);%j% %s%;}var B=%x%.GetFiles(I,"*"+a).FirstOrDefault();if(B==null){%k%d+I,a);%j% %s%;}%h%"{0} use {1}",a,B);var C=i(B).Elements().FirstOrDefault(V=^>V.Name.LocalName==b);if(C==null){%k%d,b);%j% %s%;}var _=new %f%.Collections.Generic.Dictionary^<%i%,%i%^>();Func^<%i%,%i%^>dd=de=^>_.ContainsKey(de)?_[de]:"";%m%(var df in C.Elements())_[df.Name.LocalName.ToLower()]=df.Value;if(dd(c).%r%^>100^|^|!%f%.Text.RegularExpressions.Regex.IsMatch(dd(c),@"^\w+(?:[_.-]\w+)*$")){%k%"Invalid id");%j% %s%;}var dg=%i%.Format("{0}.{1}.nupkg",dd(c),dd(A));var dh=%p%.%q%(@"$(%:%)",@"$(ngout)");if(!%i%.IsNullOrWhiteSpace(dh)){if(!%x%.%{%(dh)){%x%.%y%(dh);}dg=%p%.%q%(dh,dg);}%h%"Creating %.% {0} ...",dg);%$%(var r=Package.Open(dg,(%#%)2)){var di=new Uri(%i%.Format("/{0}{1}",dd(c),a),(UriKind)2);r.CreateRelationship(di,0,"http://schemas.microsoft.com/packaging/2010/07/manifest");%m%(var dj in %x%.GetFiles(I,"*.*",(SearchOption)1)){if(e.Any(V=^>dj.%?%(%p%.%q%(I,V.Trim('/')),(%`%)4)))continue;var dk=dj.%?%(I,(%`%)5)?dj.Substring(I.%r%).TrimStart(%p%.DirectorySeparatorChar):dj;f("+ {0}",dk);var T=r.CreatePart(PackUriHelper.CreatePartUri(new Uri(%i%.Join("/",dk.Split('\\','/').Select(Uri.EscapeDataString)),(UriKind)2)),"application/octet",(CompressionOption)1);%$%(var dl=T.GetStream())%$%(var dm=new FileStream(dj,(%#%)3,(%@%)1)){dm.CopyTo(dl);}}var dn=r.PackageProperties;dn.Creator=dd("authors");dn.Description=dd("description");dn.Identifier=dd(c);dn.Version=dd(A);dn.Keywords=dd("tags");dn.Title=dd("title");dn.LastModifiedBy="%,%/$(%,%)";}}else %j% %s%;]]^>^^^^<%b% Name="Build" DependsOnTargets="%,%"/^>^>>%ef% 33 | endlocal&exit/B0 34 | :er 35 | if defined eg set eg=!eg:%~1=! 36 | if "%~2" NEQ "" shift & goto er 37 | exit/B0 -------------------------------------------------------------------------------- /embd.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | ::! GetNuTool /shell/batch edition 3 | ::! Copyright (c) 2015-2024 Denis Kuzmin github/3F 4 | ::! https://github.com/3F/GetNuTool 5 | 6 | set gntcore=gnt.core 7 | set $tpl.corevar$="%temp%\%gntcore%$core.version$%random%%random%" 8 | 9 | set /a ERROR_FILE_NOT_FOUND=2 10 | set /a ERROR_CALL_NOT_IMPLEMENTED=120 11 | 12 | :: Syntax: 13 | :: gnt Package 14 | :: gnt "Paclage1;Package2" 15 | :: gnt 16 | :: gnt 17 | 18 | if "%~1"=="-unpack" goto unpack 19 | if "%~1"=="-msbuild" goto off 20 | 21 | set args=%* 22 | setlocal enableDelayedExpansion 23 | 24 | :: +1 space because %first:~0,1% will return literally "~0,1" as value if it's empty 25 | set "first=%~1 " 26 | set key=!first:~0,1! 27 | if "!key!" NEQ " " if !key! NEQ / set args=/p:ngpackages=!args! 28 | 29 | set "instance=%msb.gnt.cmd%" 30 | if defined instance goto found 31 | 32 | :: Find engine via msb.gnt.cmd stub or hMSBuild.bat script https://github.com/3F/hMSBuild 33 | 34 | set script=hMSBuild 35 | if exist msb.gnt.cmd set script=msb.gnt.cmd 36 | 37 | for /F "tokens=*" %%i in ('%script% -only-path 2^>^&1 ^&call echo %%^^ERRORLEVEL%%') do 2>nul ( 38 | if not defined instance ( set instance="%%i" ) else set EXIT_CODE=%%i 39 | ) 40 | 41 | if .%EXIT_CODE%==.0 if exist !instance! goto found 42 | 43 | :: Find engine via system records 44 | 45 | for %%v in (4.0, 14.0, 12.0, 3.5, 2.0) do ( 46 | for /F "usebackq tokens=2* skip=2" %%a in ( 47 | `reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\%%v" /v MSBuildToolsPath 2^> nul` 48 | ) do if exist %%b ( 49 | 50 | set instance="%%~b\MSBuild.exe" 51 | if exist !instance! ( 52 | 53 | if %%v NEQ 3.5 if %%v NEQ 2.0 goto found 54 | 55 | echo Override engine or contact for legacy support %%v 56 | exit /B %ERROR_CALL_NOT_IMPLEMENTED% 57 | ) 58 | ) 59 | ) 60 | 61 | echo Engine is not found. Try with hMSBuild 1>&2 62 | exit /B %ERROR_FILE_NOT_FOUND% 63 | 64 | :off 65 | echo This feature is disabled in current version >&2 66 | exit /B %ERROR_CALL_NOT_IMPLEMENTED% 67 | 68 | :found 69 | set con=/noconlog 70 | if "%debug%"=="true" set con=/v:q 71 | 72 | call :core 73 | call :unset "/help" "-help" "/h" "-h" "/?" "-?" 74 | 75 | call !instance! %$tpl.corevar$% /nologo /noautorsp !con! /p:wpath="%cd%/" !args! 76 | set EXIT_CODE=!ERRORLEVEL! 77 | 78 | del /Q/F %$tpl.corevar$% 79 | exit /B !EXIT_CODE! 80 | 81 | :unpack 82 | set $tpl.corevar$="%cd%\%gntcore%" 83 | echo Generating a %gntcore% at %cd%\... 84 | 85 | :core 86 | setlocal disableDelayedExpansion 87 | %$tpl.corevar$%&$gnt.core.logic$ 88 | endlocal 89 | exit /B 0 90 | 91 | :unset 92 | if defined args set args=!args:%~1=! 93 | if "%~2" NEQ "" shift & goto unset 94 | exit /B 0 -------------------------------------------------------------------------------- /tests.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | :: run tests by default 4 | 5 | setlocal 6 | if exist "core\gnt.core\" ( 7 | 8 | set "bdir=..\shell\batch\" 9 | 10 | ) else if exist "bin\Release\" ( 11 | 12 | set "bdir=..\bin\Release\" 13 | 14 | ) else goto buildError 15 | 16 | cd tests 17 | call _run gnt %bdir% 18 | endlocal 19 | 20 | exit /B 0 21 | 22 | :buildError 23 | echo. Tests cannot be started: Check your build first. >&2 24 | exit /B 1 -------------------------------------------------------------------------------- /tests/_run.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | :: Copyright (c) 2015 Denis Kuzmin github/3F 3 | 4 | :: Tests. Part of https://github.com/3F/GetNuTool 5 | :: Based on https://github.com/3F/hMSBuild 6 | 7 | setlocal enableDelayedExpansion 8 | 9 | :: path to executable version 10 | set exec=%1 11 | 12 | :: path to the directory where the release is located 13 | set rdir=%2 14 | 15 | call a isNotEmptyOrWhitespaceOrFail exec || exit /B1 16 | call a isNotEmptyOrWhitespaceOrFail rdir || exit /B1 17 | 18 | call a initAppVersion Gnt 19 | 20 | echo. 21 | call a cprint 0E ---------------- 22 | call a cprint F0 "GetNuTool .bat ~" 23 | call a cprint 0E ---------------- 24 | echo. 25 | 26 | if "!gcount!" LSS "1" set /a gcount=0 27 | if "!failedTotal!" LSS "1" set /a failedTotal=0 28 | 29 | :::::::::::::::::: :::::::::::::: ::::::::::::::::::::::::: 30 | :: Tests 31 | 32 | 33 | echo. & call a print "Tests - 'keys'" 34 | call .\keysAndLogicTests gcount failedTotal %exec% %rdir% 35 | 36 | @REM echo. & call a print "Tests - 'diffversions'" 37 | @REM call .\diffversions gcount failedTotal %exec% %rdir% %cfull% 38 | 39 | 40 | :::::::::::::::::: 41 | :: 42 | echo. 43 | call a cprint 0E ---------------- 44 | echo [Failed] = !failedTotal! 45 | set /a "gcount-=failedTotal" 46 | echo [Passed] = !gcount! 47 | call a cprint 0E ---------------- 48 | echo. 49 | 50 | if !failedTotal! GTR 0 goto failed 51 | echo. 52 | call a cprint 0A "All Passed." 53 | exit /B 0 54 | 55 | :failed 56 | echo. 57 | call a cprint 0C "Tests failed." >&2 58 | exit /B 1 59 | -------------------------------------------------------------------------------- /tests/a.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | :: Copyright (c) 2015 Denis Kuzmin github/3F 3 | :: Part of https://github.com/3F/GetNuTool 4 | 5 | if "%~1"=="" echo Empty function name & exit /B 1 6 | if .%~1 EQU .1001 call :NotRealLabel & exit /B 7 | call :shiftArgs 1,99 shProcArgs %* & call :!shProcArgs! & exit /B 8 | 9 | :initAppVersion 10 | :: [1] - Optional postfix. 11 | set /p appversion%~1=<..\.version 12 | exit /B 13 | 14 | :invoke 15 | :: (1) - Command. 16 | :: &(2) - Input arguments inside "..." via variable. 17 | :: &[3] - Return code. 18 | :: !!0+ - Error code from (1) 19 | 20 | set "cmd=%~1 !%2!" 21 | 22 | :: NOTE: Use delayed !cmd! instead of %cmd% inside `for /F` due to 23 | :: `=` (equal sign, which cannot be escaped as `^=` when runtime evaluation %cmd%) 24 | 25 | set "cmd=!cmd! 2^>^&1 ^&call echo %%^^ERRORLEVEL%%" 26 | set /a msgIdx=0 27 | 28 | for /F "tokens=*" %%i in ('!cmd!') do 2>nul ( 29 | set /a msgIdx+=1 30 | set msg[!msgIdx!]=%%i 31 | ) 32 | 33 | if not "%3"=="" set %3=!msg[%msgIdx%]! 34 | exit /B !msg[%msgIdx%]! 35 | 36 | :execute 37 | :: (1) - Command. 38 | :: !!0+ - Error code from (1) 39 | 40 | call :invoke "%~1" nul retcode 41 | exit /B !retcode! 42 | 43 | :startExTest 44 | :: (1) - Logic via :label name 45 | :: (2) - Input arguments to core inside "...". Use ` sign to apply " double quotes inside "...". 46 | :: [3] - Expected return code. Default, 0. Negative values (e.g. -1) ​​to disable checking. 47 | :: !!1 - Error code 1 if app's error code is not equal [2] as expected. 48 | 49 | set "tArgs=%~2" 50 | if "%~3"=="" ( set /a exCode=0 ) else set /a exCode=%~3 51 | 52 | if "!tArgs!" NEQ "" set tArgs=!tArgs:`="! 53 | 54 | set /a gcount+=1 55 | echo. 56 | echo - - - - - - - - - - - - 57 | echo Test #%gcount% @ %TIME% 58 | echo - - - - - - - - - - - - 59 | echo keys: !tArgs! 60 | echo. 61 | 62 | set callback=%~1 & shift 63 | 64 | goto %callback% 65 | :_logicExTestEnd 66 | 67 | if %exCode% LSS 0 exit /B 0 68 | if "!retcode!" NEQ "%exCode%" call :failTest & exit /B 1 69 | exit /B 0 70 | 71 | :startTest 72 | :: (1) - Input arguments to core inside "...". Use ` sign to apply " double quotes inside "...". 73 | :: [2] - Expected return code. Default, 0. 74 | :: !!1 - Error code 1 if app's error code is not equal [2] as expected. 75 | 76 | call :startExTest _logicStartTest %* 77 | exit /B 78 | :_logicStartTest 79 | call :invoke "%wdir%%exec%" tArgs retcode 80 | 81 | goto _logicExTestEnd 82 | :: :startTest 83 | 84 | :startABTest 85 | :: (1) - Input arguments inside "...". Use ` sign to apply " double quotes inside "...". 86 | :: (2) - A command 87 | :: (3) - B command 88 | :: &(4) - Result from (2) A 89 | :: &(5) - Result from (3) B 90 | 91 | set "exA=%2" & set "exB=%3" 92 | set "_4=%4" 93 | set "_5=%5" 94 | 95 | call :startExTest _logicStartABTest %1 96 | exit /B 97 | :_logicStartABTest 98 | call :invoke !exA! tArgs retcodeA & call :getMsgAt 1 outA 99 | call :invoke !exB! tArgs retcodeB & call :getMsgAt 1 outB 100 | 101 | set %_4%=!outA! !retcodeA! 102 | set %_5%=!outB! !retcodeB! 103 | set /a retcode=0 104 | 105 | goto _logicExTestEnd 106 | :: :startABTest 107 | 108 | :startABStreamTest 109 | :: (1) - Input arguments inside "...". Use ` sign to apply " double quotes inside "...". 110 | :: (2) - A command 111 | :: (3) - B command 112 | :: [4] - Expected return code. Default, 0. 113 | :: &*[5] - Result stream from (2) A; e.g. !%argname%[n+]! 114 | 115 | set "exA=%2" & set "exB=%3" 116 | set "_5=%5" 117 | 118 | call :startExTest _logicStartABStreamTest "-debug %~1" %~4 119 | exit /B 120 | :_logicStartABStreamTest 121 | 122 | :: Disables time [ 21:50:25.46 ] as [ - ] 123 | set "TIME=-" 124 | 125 | call :invoke !exA! tArgs retcodeA 126 | call :cloneStreamAs _streamA 127 | call :invoke !exB! tArgs retcodeB 128 | 129 | set /a retcode=%retcodeB% 130 | call :eqOriginStreamWithOrFail _streamA 1 || set /a retcode=1 131 | 132 | set "TIME=" 133 | if defined _5 set %_5%=_streamA 134 | 135 | goto _logicExTestEnd 136 | :: :startABStreamTest 137 | 138 | :abStreamTest 139 | :: (1) - Input arguments inside "...". Use ` sign to apply " double quotes inside "...". 140 | :: (2) - A command 141 | :: (3) - B command 142 | :: [4] - Expected return code. Default, 0. 143 | 144 | call :startABStreamTest "%~1" "%~2" "%~3" %~4 || exit /B 1 145 | call :completeTest 146 | exit /B 0 147 | 148 | :startVFTest 149 | :: (1) - Input core application. 150 | :: (2) - Input arguments to core inside "...". Use ` sign to apply " double quotes inside "...". 151 | :: (3) - Full path to actual data in the file system. 152 | :: &(4) - Return actual data. 153 | 154 | set _exapp="%~1" 155 | set _lwrap="%~3" 156 | set "_4=%4" 157 | 158 | call :startExTest _logicStartVFTest %2 159 | exit /B 160 | :_logicStartVFTest 161 | call :invoke %_exapp% tArgs retcode 162 | for /f "usebackq tokens=*" %%i in (`type %_lwrap%`) do set "%_4%=%%i" 163 | 164 | goto _logicExTestEnd 165 | :: :startVFTest 166 | 167 | :completeTest 168 | call :cprint 27 [Passed] 169 | exit /B 0 170 | 171 | :failTest 172 | :: [1] - Optional message string. 173 | 174 | set /a "failedTotal+=1" 175 | 176 | if not "%~1"=="" echo %~1 177 | call :printStream failed 178 | echo. & call :cprint 47 [Failed] 179 | exit /B 0 180 | 181 | :printStream 182 | if "!msgIdx!"=="" exit /B 1 183 | for /L %%i in (0,1,!msgIdx!) do echo (%%i) *%~1: !msg[%%i]! 184 | exit /B 0 185 | 186 | :printStreamAB 187 | :: &(1) - Stream name to print together with origin. 188 | 189 | if "!msgIdx!"=="" exit /B 1 190 | for /L %%i in (0,1,!msgIdx!) do ( 191 | echo `!_streamA[%%i]!` & echo `!msg[%%i]!` & echo -- 192 | ) 193 | exit /B 0 194 | 195 | :failStreamsTest 196 | :: &(1) - Stream name to print together with origin. 197 | :: [2] - Don't count in the total counter if 1. 198 | 199 | if "%~2" NEQ "1" set /a "failedTotal+=1" 200 | call :printStreamAB %~1 201 | exit /B 0 202 | 203 | :contains 204 | :: &(1) - Input string via variable 205 | :: (2) - Substring to check. Use ` instead of " and do NOT use =(equal sign) since it's not protected. 206 | :: &(3) - Result, 1 if found. 207 | 208 | :: TODO: L-39 protect from `=` like the main module does; or compare in parts using `#` 209 | 210 | set "input=!%~1!" 211 | 212 | if "%~2"=="" if "!input!"=="" set /a %3=1 & exit /B 0 213 | if "!input!"=="" if not "%~2"=="" set /a %3=0 & exit /B 0 214 | 215 | set "input=!input:"=`!" 216 | set "cmp=!input:%~2=!" 217 | 218 | if "!cmp!" NEQ "!input!" ( set /a %3=1 ) else set /a %3=0 219 | exit /B 0 220 | 221 | :printMsgAt 222 | :: (1) - index at msg 223 | :: [2] - color attribute via :color call 224 | :: [3] - prefixed message at the same line 225 | :: !!1 - Error code 1 if &(1) is empty or not valid. 226 | 227 | call :getMsgAt %~1 _msgstr || exit /B 1 228 | 229 | if not "%~2"=="" ( 230 | call :cprint %~2 "%~3!_msgstr!" 231 | 232 | ) else echo !_msgstr! 233 | exit /B 0 234 | 235 | :getMsgAt 236 | :: (1) - index at msg 237 | :: &(2) - result string 238 | :: !!1 - Error code 1 if &(1) is empty or not valid. 239 | 240 | if "%~1"=="" exit /B 1 241 | if %msgIdx% LSS %~1 exit /B 1 242 | if %~1 LSS 0 exit /B 1 243 | 244 | set %2=!msg[%~1]! 245 | exit /B 0 246 | 247 | :msgAt 248 | :: (1) - index at msg 249 | :: (2) - substring to check 250 | :: &(3) - result, 1 if found. 251 | 252 | set /a %3=0 253 | call :getMsgAt %~1 _msgstr || exit /B 0 254 | 255 | call :contains _msgstr "%~2" _n & set /a %3=!_n! 256 | exit /B 0 257 | 258 | :msgOrFailAt 259 | :: (1) - index at msg 260 | :: (2) - substring to check 261 | :: !!1 - Error code 1 if the message is not found at the specified index. 262 | 263 | call :msgAt %~1 "%~2" _n & if .!_n! NEQ .1 call :failTest & exit /B 1 264 | exit /B 0 265 | 266 | :checkFs 267 | :: (1) - Path to directory that must be available or to file that must exist. 268 | :: [2] - An optional path to a file that must exist in an accessible directory (1). 269 | :: !!1 - Error code 1 if the directory or file does not exist. 270 | 271 | if not exist "%~1" call :failTest & exit /B 1 272 | if not "%~2"=="" if not exist "%~1\%~2" call :failTest & exit /B 1 273 | exit /B 0 274 | 275 | :checkFsBase 276 | :: (1) - Path to directory that must be available. 277 | :: (2) - Path to the file that must exist. 278 | :: !!1 - Error code 1 if the directory or file does not exist. 279 | 280 | call :checkFs "%basePkgDir%%~1" "%~2" 281 | exit /B 282 | 283 | :checkFsNo 284 | :: (1) - Path to the file or directory that must NOT exist. 285 | :: !!1 - Error code 1 if the specified path exists. 286 | 287 | if exist "%~1" call :failTest & exit /B 1 288 | exit /B 0 289 | 290 | :checkFsBaseNo 291 | :: (1) - Path to the file or directory that must NOT exist. 292 | :: !!1 - Error code 1 if the specified path exists. 293 | 294 | call :checkFsNo "%basePkgDir%%~1" 295 | exit /B 296 | 297 | :unsetDir 298 | :: (1) - Path to directory. 299 | call :isStrNotEmptyOrWhitespaceOrFail "%~1" || exit /B 1 300 | rmdir /S/Q "%~1" 2>nul 301 | exit /B 0 302 | 303 | :unsetPackage 304 | :: (1) - Package directory. 305 | call :unsetDir "%basePkgDir%%~1" 306 | exit /B 0 307 | 308 | :unsetFile 309 | :: (1) - File name. 310 | call :isStrNotEmptyOrWhitespaceOrFail "%~1" || exit /B 1 311 | del /Q "%~1" 2>nul 312 | exit /B 0 313 | 314 | :unsetNupkg 315 | :: (1) - Nupkg file name. 316 | call :unsetFile "%~1" 317 | exit /B 0 318 | 319 | :checkFsNupkg 320 | :: (1) - Nupkg file name. 321 | :: !!1 - Error code 1 if the input (1) does not exist. 322 | 323 | if not exist "%~1" call :failTest & exit /B 1 324 | exit /B 0 325 | 326 | :findInStream 327 | :: (1) - substring to check 328 | :: [2] - Start index, 0 by default. 329 | :: &[3] - Return index or -1 if not found. 330 | :: !!1 - Error code 1 if failed. 331 | :: !!3 - Error code 3 if not found. 332 | 333 | if "%~2"=="" (set /a _sidx=0) else set /a _sidx=%~2 334 | if %_sidx% LSS 0 exit /B 1 335 | if %msgIdx% LSS %_sidx% exit /B 1 336 | 337 | for /L %%i in (%_sidx%,1,!msgIdx!) do ( 338 | call :msgAt %%i "%~1" _n & if .!_n! EQU .1 ( 339 | if not "%~3"=="" set /a %3=%%i 340 | exit /B 0 341 | ) 342 | ) 343 | if not "%~3"=="" set /a %3=-1 344 | exit /B 3 345 | 346 | :findInStreamOrFail 347 | :: (1) - substring to check 348 | :: [2] - Start index, 0 by default. 349 | :: &[3] - Return index or -1 if not found. 350 | :: !!1 - Error code 1 if failed. 351 | 352 | call :findInStream "%~1" %~2 %~3 || ( call :failTest & exit /B 1 ) 353 | exit /B 0 354 | 355 | :failIfInStream 356 | :: (1) - substring to check 357 | :: !!1 - Error code 1 if the input (1) was not found. 358 | 359 | call :findInStream "%~1" _n & if .!_n! EQU .1 ( call :failTest & exit /B 1 ) 360 | exit /B 0 361 | 362 | :print 363 | :: (1) - Input string. 364 | 365 | :: NOTE: delayed `dmsg` because symbols like `)`, `(` ... requires protection after expansion. L-32 366 | set "dmsg=%~1" & echo [ %TIME% ] !dmsg! 367 | exit /B 0 368 | 369 | :cprint 370 | :: (1) - color attribute via :color call 371 | :: (2) - Input string. 372 | 373 | call :color %~1 "%~2" & echo. 374 | exit /B 0 375 | 376 | :color 377 | :: (1) - color attribute, {background} | {foreground} 378 | :: 0 = Black 8 = Gray 379 | :: 1 = Blue 9 = Light Blue 380 | :: 2 = Green A = Light Green 381 | :: 3 = Aqua B = Light Aqua 382 | :: 4 = Red C = Light Red 383 | :: 5 = Purple D = Light Purple 384 | :: 6 = Yellow E = Light Yellow 385 | :: 7 = White F = Bright White 386 | 387 | :: (2) - Input string. 388 | 389 | "%~2" 390 | findstr /a:%~1  "%~2" nul 391 | del "%~2">nul 392 | exit /B 0 393 | 394 | :isNotEmptyOrWhitespace 395 | :: &(1) - Input variable. 396 | :: !!1 - Error code 1 if &(1) is empty or contains only whitespace characters. 397 | 398 | set "_v=!%~1!" 399 | if not defined _v exit /B 1 400 | 401 | set _v=%_v: =% 402 | if not defined _v exit /B 1 403 | 404 | :: e.g. set a="" not set "a=" 405 | exit /B 0 406 | 407 | :sha1At0 408 | :: (1) - Stream index. 409 | :: &(2) - sha1 result. 410 | set %2=!msg[%~1]:~4,40! 411 | exit /B 0 412 | 413 | :sha1At 414 | :: (1) - Stream index. 415 | :: &(2) - sha1 result. 416 | set %2=!msg[%~1]:~45,40! 417 | exit /B 0 418 | 419 | :errargs 420 | echo. 421 | echo. Incorrect arguments. >&2 422 | exit /B 1 423 | 424 | :isNotEmptyOrWhitespaceOrFail 425 | :: &(1) - Input variable. 426 | :: !!1 - Error code 1 if &(1) is empty or contains only whitespace characters. 427 | call :isNotEmptyOrWhitespace %1 || (call :errargs & exit /B 1) 428 | exit /B 0 429 | 430 | :isStrNotEmptyOrWhitespaceOrFail 431 | :: (1) - Input string. 432 | :: !!1 - Error code 1 if (1) is empty or contains only whitespace characters. 433 | set "_wstrv=%~1" 434 | call :isNotEmptyOrWhitespaceOrFail _wstrv 435 | exit /B 436 | 437 | :cloneStreamAs 438 | :: &(1) - Destination. 439 | 440 | for /L %%i in (0,1,!msgIdx!) do set "%~1[%%i]=!msg[%%i]!" 441 | exit /B 442 | 443 | :eqOriginStreamWith 444 | :: &(1) - Current stream with stream from (1). 445 | :: &(2) - Return 1 if both streams are equal. 446 | 447 | for /L %%i in (0,1,!msgIdx!) do ( 448 | if not "!%~1[%%i]!"=="!msg[%%i]!" ( set "%2=0" & exit /B 0 ) 449 | ) 450 | set "%2=1" 451 | exit /B 0 452 | 453 | :eqOriginStreamWithOrFail 454 | :: &(1) - Current stream with stream from (1). 455 | :: [2] - Don't count in the total counter if 1. 456 | 457 | call :eqOriginStreamWith %~1 _r & if !_r! EQU 0 ( 458 | call :failStreamsTest %~1 %~2 & exit /B 1 459 | ) 460 | exit /B 0 461 | 462 | :disableAppVersion 463 | :: [1] - Optional postfix. 464 | set "appversion%~1=off" 465 | exit /B 0 466 | 467 | :shiftArgs 468 | :: (1) - Start index from 1. 469 | :: (2) - End index. 470 | :: &(3) - Result. 471 | :: [4+] - %* 472 | 473 | set /a idx=0 474 | set /a start=%~1 + 2 475 | set /a end=%~2 + 1 476 | set "ret=" & set "rName=%3" 477 | :_shiftArg 478 | shift & set /a idx+=1 479 | if %idx% LSS %start% if "%~1" NEQ "" goto _shiftArg 480 | 481 | :: Y-60, hMSBuild; don't use `set "ret=!ret!%1 "` due to "..." and `&`, `|`, etc. 482 | set ret=!ret!%1 483 | 484 | :: NOTE: give preference to `defined` because of possible empty "" (a two double quotes together) 485 | set _argf=%1 486 | if defined _argf set ret=!ret!,& if %idx% LEQ %end% goto _shiftArg 487 | 488 | set "%rName%=!ret!" 489 | exit /B 0 490 | 491 | :initGlobalUnspecLabelMsg 492 | :: (G_UnspecLabelMsg) - Pattern when the system cannot find the label. 493 | if not defined G_UnspecLabelMsg call :getUnspecLabelMsg G_UnspecLabelMsg 494 | exit /B 0 495 | 496 | :getUnspecLabelMsg 497 | :: &(1) - Output message. 498 | 499 | for /F "tokens=*" %%i in ('%~dpnx0 1001 2^>^&1') do set _ul_msg=%%i 500 | set "%~1=%_ul_msg:NotRealLabel=%" 501 | exit /B 0 502 | 503 | :thisOrBase 504 | :: (1) - Process return code. 505 | :: (2) - Process stderr via file. 506 | :: (3) - Use a negative number (less than 0) to finish processing. 507 | 508 | set "_msgErr=" & set /p _msgErr=<%2 509 | 510 | if .%~1 NEQ .1 ( 511 | if defined _msgErr echo !_msgErr! >&2 512 | exit /B 0 513 | ) 514 | 515 | call :initGlobalUnspecLabelMsg 516 | call :contains _msgErr "%G_UnspecLabelMsg%" _n 517 | if .!_n! NEQ .1 ( 518 | if defined _msgErr echo !_msgErr! >&2 519 | exit /B 0 520 | ) 521 | 522 | if %~3 LEQ -1 if defined _msgErr echo !_msgErr! >&2 523 | exit /B 1 524 | 525 | :tryThisOrBase 526 | :: (1) - Process return code. 527 | :: (2) - Process stderr via file. 528 | :: [3-9] 529 | :: (G_AutoCleanThisOrBase) 530 | 531 | if .%~1 EQU .0 set "_currentLevelTOB=" & exit /B 0 532 | 533 | if !_currentLevelTOB! LSS 0 set "_currentLevelTOB=" 534 | if not defined _currentLevelTOB set /a _currentLevelTOB=G_LevelChild*2-1 535 | 536 | set /a _currentLevelTOB-=1 537 | 538 | set /a rCode=%~1 539 | call :thisOrBase %~1 %2 0 || ( 540 | 541 | :: TODO: (performance) reduce the number of I/O interruptions 542 | call :shiftArgs 3,99 shArgs %* & call :!shArgs! 2>%2 543 | set /a rCode=!ERRORLEVEL! 544 | call :thisOrBase !rCode! %2 !_currentLevelTOB! 545 | ) 546 | if defined G_AutoCleanThisOrBase call :cleanForThisOrBase %2 547 | exit /B !rCode! 548 | 549 | :cleanForThisOrBase 550 | :: [1] - Optional specific .err file. 551 | 552 | set _cltf=%2 553 | if not defined _cltf set _cltf=%~nx0.err 554 | del /Q/F %_cltf% 2>nul 555 | exit /B 0 556 | -------------------------------------------------------------------------------- /tests/keysAndLogicTests.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | :: Copyright (c) 2015 Denis Kuzmin github/3F 3 | 4 | :: Tests. Part of https://github.com/3F/GetNuTool 5 | 6 | setlocal enableDelayedExpansion 7 | call a isNotEmptyOrWhitespaceOrFail %~1 || exit /B1 8 | 9 | set /a gcount=!%~1! & set /a failedTotal=!%~2! 10 | set "exec=%~3" & set "wdir=%~4" 11 | 12 | :::::::::::::::::: :::::::::::::: ::::::::::::::::::::::::: 13 | :: Tests 14 | 15 | set "basePkgDir=packages\" 16 | set "artefactsDirName=_artefacts" 17 | set "ngpackages=" 18 | set "logo=" 19 | set "gntcore=gnt.core" 20 | set "config=%basePkgDir%packages.config" 21 | call a unsetFile %config% 22 | 23 | :: NOTE: :startTest will use ` as " 24 | :: It helps to use double quotes inside double quotes " ... `args` ... " 25 | 26 | ::::::::::::::::: 27 | call :cleanup 28 | 29 | ::_______ ------ ______________________________________ 30 | 31 | call a startTest "" 1 || goto x 32 | call a msgOrFailAt 0 "" || goto x 33 | 34 | if not defined appversionGnt call a failTest "Empty *appversionGnt" & goto x 35 | if not "%appversionGnt%"=="off" ( 36 | call a msgOrFailAt 1 "GetNuTool %appversionGnt%" || goto x 37 | ) 38 | call a msgOrFailAt 2 "github/3F" || goto x 39 | call a msgOrFailAt 3 "Empty .config + ngpackages" || goto x 40 | call a completeTest 41 | ::_____________________________________________________ 42 | 43 | 44 | ::_______ ------ ______________________________________ 45 | 46 | call a startTest "/p:debug=true" 1 || goto x 47 | call a msgOrFailAt 0 "" || goto x 48 | 49 | if not defined appversionGnt call a failTest "Empty *appversionGnt" & goto x 50 | if not "%appversionGnt%"=="off" ( 51 | call a msgOrFailAt 1 "GetNuTool %appversionGnt%" || goto x 52 | ) 53 | call a msgOrFailAt 2 "github/3F" || goto x 54 | call a msgOrFailAt 3 "packages.config is not found" || goto x 55 | call a msgOrFailAt 4 ".tools\packages.config is not found" || goto x 56 | call a msgOrFailAt 5 "Empty .config + ngpackages" || goto x 57 | call a completeTest 58 | ::_____________________________________________________ 59 | 60 | 61 | set "logo=no" 62 | 63 | ::_______ ------ ______________________________________ 64 | 65 | call a unsetPackage Fnv1a128 66 | 67 | call a startTest "Fnv1a128" || goto x 68 | call a msgOrFailAt 1 "Fnv1a128 ... " || goto x 69 | call a checkFsBaseNo "Fnv1a128/_rels/" || goto x 70 | call a checkFsBaseNo "Fnv1a128/package/" || goto x 71 | call a checkFsBaseNo "Fnv1a128/[Content_Types].xml" || goto x 72 | call a completeTest 73 | ::_____________________________________________________ 74 | 75 | 76 | ::_______ ------ ______________________________________ 77 | 78 | call a startTest "Fnv1a128" || goto x 79 | call a msgOrFailAt 1 "Fnv1a128 use " || goto x 80 | call a checkFsBase "Fnv1a128" "Fnv1a128.nuspec" || goto x 81 | call a completeTest 82 | ::_____________________________________________________ 83 | 84 | 85 | ::_______ ------ ______________________________________ 86 | 87 | call a startTest "`Fnv1a128`" || goto x 88 | call a msgOrFailAt 1 "Fnv1a128 use " || goto x 89 | call a checkFsBase "Fnv1a128" "Fnv1a128.nuspec" || goto x 90 | call a completeTest 91 | ::_____________________________________________________ 92 | 93 | 94 | ::_______ ------ ______________________________________ 95 | 96 | set ngpackages=Fnv1a128 97 | call a startTest || goto x 98 | call a msgOrFailAt 1 "Fnv1a128 use " || goto x 99 | call a checkFsBase "Fnv1a128" "Fnv1a128.nuspec" || goto x 100 | call a completeTest 101 | set "ngpackages=" 102 | ::_____________________________________________________ 103 | 104 | 105 | ::_______ ------ ______________________________________ 106 | 107 | call a unsetPackage Fnv1a128.1.0.0 108 | 109 | call a startTest "Fnv1a128/1.0.0?cccccccccccccccccccccccccccccccccccccccc" 1 || goto x 110 | call a msgOrFailAt 1 "Fnv1a128/1.0.0 ... " || goto x 111 | call a msgOrFailAt 2 "[x]" || goto x 112 | call a sha1At 2 sha1Fnv1a128 113 | call a checkFsBaseNo "Fnv1a128.1.0.0/Fnv1a128.nuspec" || goto x 114 | call a completeTest 115 | ::_____________________________________________________ 116 | 117 | 118 | ::_______ ------ ______________________________________ 119 | 120 | call a startTest "Fnv1a128/1.0.0?!sha1Fnv1a128!" || goto x 121 | call a msgOrFailAt 1 "Fnv1a128/1.0.0 ... " || goto x 122 | call a msgOrFailAt 2 "!sha1Fnv1a128! ... !sha1Fnv1a128!" || goto x 123 | call a checkFsBase "Fnv1a128.1.0.0" "Fnv1a128.nuspec" || goto x 124 | call a completeTest 125 | ::_____________________________________________________ 126 | 127 | 128 | ::_______ ------ ______________________________________ 129 | 130 | call a unsetPackage Conari 131 | 132 | call a startTest "Conari" || goto x 133 | call a msgOrFailAt 1 "Conari ... " || goto x 134 | call a checkFsBase "Conari" "Conari.nuspec" || goto x 135 | call a completeTest 136 | ::_____________________________________________________ 137 | 138 | 139 | ::_______ ------ ______________________________________ 140 | 141 | call a startTest "`Fnv1a128;Conari`" || goto x 142 | call a msgOrFailAt 1 "Fnv1a128 use " || goto x 143 | call a msgOrFailAt 2 "Conari use " || goto x 144 | call a checkFsBase "Fnv1a128" "Fnv1a128.nuspec" || goto x 145 | call a checkFsBase "Conari" "Conari.nuspec" || goto x 146 | call a completeTest 147 | ::_____________________________________________________ 148 | 149 | 150 | ::_______ ------ ______________________________________ 151 | 152 | call a unsetPackage regXwild.1.4.0 153 | 154 | call a startTest "regXwild/1.4.0" || goto x 155 | call a msgOrFailAt 1 "regXwild/1.4.0 ... " || goto x 156 | call a checkFsBase "regXwild.1.4.0" "regXwild.nuspec" || goto x 157 | call a completeTest 158 | ::_____________________________________________________ 159 | 160 | 161 | ::_______ ------ ______________________________________ 162 | 163 | set "expNupkg=regXwild.1.4.0.nupkg" 164 | call a unsetNupkg %expNupkg% 165 | 166 | call a startTest "/t:pack /p:ngin=%basePkgDir%regXwild.1.4.0" || goto x 167 | call a msgOrFailAt 1 ".nuspec use " || goto x 168 | call a msgOrFailAt 2 "Creating package " || goto x 169 | call a checkFsNupkg %expNupkg% || goto x 170 | call a completeTest 171 | 172 | call a unsetNupkg %expNupkg% 173 | ::_____________________________________________________ 174 | 175 | 176 | ::_______ ------ ______________________________________ 177 | 178 | call a unsetNupkg "%basePkgDir%Huid.nupkg" 179 | 180 | call a startTest "Huid/1.0.0:Huid.nupkg /t:grab" || goto x 181 | call a msgOrFailAt 1 "Huid/1.0.0 ... " || goto x 182 | call a msgOrFailAt 1 "\Huid.nupkg" || goto x 183 | call a checkFsNupkg "%basePkgDir%Huid.nupkg" || goto x 184 | call a completeTest 185 | ::_____________________________________________________ 186 | 187 | 188 | ::_______ ------ ______________________________________ 189 | 190 | call a startTest "/p:ngpackages=Huid/1.0.0:Huid.nupkg /t:grab" || goto x 191 | call a msgOrFailAt 1 "Huid.1.0.0 use " || goto x 192 | call a msgOrFailAt 1 "\Huid.nupkg" || goto x 193 | call a checkFsNupkg "%basePkgDir%Huid.nupkg" || goto x 194 | call a completeTest 195 | ::_____________________________________________________ 196 | 197 | 198 | ::_______ ------ ______________________________________ 199 | 200 | call a unsetPackage Huid.local 201 | 202 | call a startTest "/p:ngpackages=:Huid.local /p:ngserver=file:///%cd%\%basePkgDir%Huid.nupkg" || goto x 203 | call a msgOrFailAt 1 "... %cd%\%basePkgDir%Huid.local" || goto x 204 | call a checkFsBase "Huid.local" "Huid.nuspec" || goto x 205 | call a completeTest 206 | ::_____________________________________________________ 207 | 208 | 209 | ::_______ ------ ______________________________________ 210 | 211 | call a unsetPackage Huid.local 212 | 213 | call a startTest ":Huid.local /p:ngserver=%cd%\%basePkgDir%Huid.nupkg /p:debug=true" || goto x 214 | call a msgOrFailAt 1 "... " || goto x 215 | call a msgOrFailAt 2 "/.version" || goto x 216 | call a msgOrFailAt 3 "/3rd-party-notices.txt" || goto x 217 | call a msgOrFailAt 11 "/lib/net5.0/Huid.dll" || goto x 218 | call a msgOrFailAt 19 "/tools/gnt.bat" || goto x 219 | call a checkFsBase "Huid.local" "Huid.nuspec" || goto x 220 | call a completeTest 221 | ::_____________________________________________________ 222 | 223 | 224 | ::_______ ------ ______________________________________ 225 | 226 | call a unsetPackage ..\T00LS 227 | 228 | call a startTest "/p:ngserver=%cd%\%basePkgDir%Huid.nupkg /p:ngpackages=: /p:ngpath=T00LS" || goto x 229 | call a msgOrFailAt 1 "... %cd%\T00LS" || goto x 230 | call a checkFs "T00LS" "Huid.nuspec" || goto x 231 | call a completeTest 232 | 233 | call a unsetPackage ..\T00LS 234 | ::_____________________________________________________ 235 | 236 | 237 | ::_______ ------ ______________________________________ 238 | 239 | call a unsetPackage putty.portable.0.69 240 | 241 | call a startTest "/p:ngpackages=putty.portable/0.69 /p:ngserver=https://chocolatey.org/api/v2/package/" || goto x 242 | call a msgOrFailAt 1 "putty.portable/0.69 ... " || goto x 243 | call a checkFsBase "putty.portable.0.69" "putty.portable.nuspec" || goto x 244 | call a completeTest 245 | ::_____________________________________________________ 246 | 247 | 248 | ::_______ ------ ______________________________________ 249 | 250 | call a startTest "/p:ngpackages=`Conari;Fnv1a12;LX4Cnh` /p:break=no" || goto x 251 | call a msgOrFailAt 1 "Conari " || goto x 252 | call a msgOrFailAt 2 "Fnv1a12 ... " || goto x 253 | call a msgOrFailAt 2 "404" || goto x 254 | call a msgOrFailAt 3 "LX4Cnh " || goto x 255 | call a completeTest 256 | ::_____________________________________________________ 257 | 258 | 259 | ::_______ ------ ______________________________________ 260 | 261 | call a startTest "`Conari;Fnv1a12;LX4Cnh` /p:break=no" || goto x 262 | call a msgOrFailAt 1 "Conari " || goto x 263 | call a msgOrFailAt 2 "Fnv1a12 ... " || goto x 264 | call a msgOrFailAt 2 "404" || goto x 265 | call a msgOrFailAt 3 "LX4Cnh " || goto x 266 | call a completeTest 267 | ::_____________________________________________________ 268 | 269 | 270 | ::_______ ------ ______________________________________ 271 | 272 | call a startTest "`Conari;Fnv1a12;LX4Cnh` /p:break=yes" 1 || goto x 273 | call a msgOrFailAt 1 "Conari " || goto x 274 | call a msgOrFailAt 2 "Fnv1a12 ... " || goto x 275 | call a msgOrFailAt 2 "404" || goto x 276 | call a completeTest 277 | ::_____________________________________________________ 278 | 279 | 280 | ::_______ ------ ______________________________________ 281 | 282 | echo ^>>%config% 283 | 284 | call a startTest "/p:ngconfig=`%config%`" 1 || goto x 285 | call a msgOrFailAt 1 "Root element is missing" || goto x 286 | call a completeTest 287 | ::_____________________________________________________ 288 | 289 | 290 | ::_______ ------ ______________________________________ 291 | 292 | echo ^>%config% 293 | echo ^>>%config% 294 | echo ^>>%config% 295 | echo ^>>%config% 296 | echo ^>>%config% 297 | echo ^>>%config% 298 | 299 | call a startTest "/p:ngconfig=`%config%`" || goto x 300 | call a msgOrFailAt 1 "Conari use " || goto x 301 | call a msgOrFailAt 2 "Fnv1a128.1.0.0 use " || goto x 302 | call a msgOrFailAt 3 "LX4Cnh/1.1.0 ... " || goto x 303 | call a checkFsBase "Conari" "Conari.nuspec" || goto x 304 | call a checkFsBase "Fnv1a128.1.0.0" "Fnv1a128.nuspec" || goto x 305 | call a checkFsBase "__algorithms" "LX4Cnh.nuspec" || goto x 306 | call a completeTest 307 | ::_____________________________________________________ 308 | 309 | 310 | ::_______ ------ ______________________________________ 311 | 312 | set "cfg1=%basePkgDir%p1.config" 313 | echo ^>%cfg1% 314 | echo ^>>%cfg1% 315 | echo ^>>%cfg1% 316 | echo ^>>%cfg1% 317 | 318 | set "cfg2=%basePkgDir%p2.config" 319 | echo ^>%cfg2% 320 | echo ^>>%cfg2% 321 | echo ^>>%cfg2% 322 | echo ^>>%cfg2% 323 | 324 | call a startTest "/p:ngconfig=`%cfg1%;%cfg2%`" || goto x 325 | call a msgOrFailAt 1 "LX4Cnh" || goto x 326 | call a msgOrFailAt 2 "Conari " || goto x 327 | call a checkFsBase "__algorithms" "LX4Cnh.nuspec" || goto x 328 | call a checkFsBase "Conari" "Conari.nuspec" || goto x 329 | call a completeTest 330 | 331 | call a unsetFile %cfg1% 332 | call a unsetFile %cfg2% 333 | ::_____________________________________________________ 334 | 335 | 336 | ::_______ ------ ______________________________________ 337 | 338 | call a unsetNupkg %basePkgDir%%artefactsDirName%\Fnv1a128.1.0.0.nupkg 339 | 340 | call a startTest "/t:pack /p:ngin=%basePkgDir%Fnv1a128.1.0.0 /p:ngout=%artefactsDirName% /p:debug=true" || goto x 341 | call a msgOrFailAt 2 "Creating package " || goto x 342 | call a msgOrFailAt 2 "Fnv1a128.1.0.0.nupkg" || goto x 343 | call a msgOrFailAt 6 "Fnv1a128.nuspec" || goto x 344 | call a msgOrFailAt 11 "Fnv1a128.dll" || goto x 345 | call a checkFs %artefactsDirName% "Fnv1a128.1.0.0.nupkg" || goto x 346 | 347 | :: it should fail due to 1 error code but let's check it to be sure 348 | call a failIfInStream "+ [Content_Types].xml" || goto x 349 | call a failIfInStream "+ package\" || goto x 350 | call a failIfInStream "+ _rels\.rels" || goto x 351 | call a completeTest 352 | ::_____________________________________________________ 353 | 354 | 355 | ::_______ ------ ______________________________________ 356 | 357 | call a unsetNupkg %basePkgDir%%artefactsDirName%\Fnv1a128.1.0.0.nupkg 358 | 359 | call a startTest "/t:pack /p:ngin=Fnv1a128.1.0.0 /p:wpath=%cd%\%basePkgDir% /p:ngout=%artefactsDirName%" || goto x 360 | call a msgOrFailAt 1 ".nuspec " || goto x 361 | call a msgOrFailAt 2 "Creating package " || goto x 362 | call a msgOrFailAt 2 "Fnv1a128.1.0.0.nupkg" || goto x 363 | call a checkFsBase %artefactsDirName% "Fnv1a128.1.0.0.nupkg" || goto x 364 | call a completeTest 365 | ::_____________________________________________________ 366 | 367 | 368 | ::_______ ------ ______________________________________ 369 | 370 | :: NOTE: In original engine, the trailing backslash \ inside "..." must be escaped at least before the last double quote (i.e. \" in "...\path\"), 371 | :: for example, by adding a new one "...\path\\" or "...\path\/" or removed at all "...\path" or escape every backslash "dir1\\dir2\\path\\" or use the common slash "dir1/dir2/path/" instead 372 | call a startTest "/t:pack /p:ngin=Fnv1a128.1.0.0 /p:wpath=`%cd%\%basePkgDir%\`" || goto x 373 | call a msgOrFailAt 1 ".nuspec " || goto x 374 | call a msgOrFailAt 2 "Creating package " || goto x 375 | call a msgOrFailAt 2 "Fnv1a128.1.0.0.nupkg" || goto x 376 | call a checkFsBase %artefactsDirName% "Fnv1a128.1.0.0.nupkg" || goto x 377 | call a completeTest 378 | ::_____________________________________________________ 379 | 380 | 381 | ::_______ ------ ______________________________________ 382 | 383 | call a startTest "/p:wpath=%cd%\%basePkgDir%" || goto x 384 | call a msgOrFailAt 1 "Conari " || goto x 385 | call a msgOrFailAt 2 "Fnv1a128" || goto x 386 | call a msgOrFailAt 3 "!sha1Fnv1a128! ... !sha1Fnv1a128!" || goto x 387 | call a msgOrFailAt 4 "LX4Cnh" || goto x 388 | call a completeTest 389 | ::_____________________________________________________ 390 | 391 | 392 | ::_______ ------ ______________________________________ 393 | 394 | call a unsetFile %gntcore% 395 | 396 | :: NOTE: sha1_comparer compares both cores when running build.bat 397 | 398 | call a startTest "-unpack " || goto x 399 | call a msgOrFailAt 1 "Generating a %gntcore% at " || goto x 400 | call a checkFs %gntcore% 401 | call a completeTest 402 | 403 | call a unsetFile %gntcore% 404 | ::_____________________________________________________ 405 | 406 | 407 | ::_______ ------ ______________________________________ 408 | 409 | call a unsetPackage Fnv1a128.1.0.0 410 | 411 | echo ^>%config% 412 | echo ^>>%config% 413 | echo ^>>%config% 414 | echo ^>>%config% 415 | 416 | call a startTest "/p:ngconfig=`%config%`" 1 || goto x 417 | call a msgOrFailAt 1 "Fnv1a128/1.0.0 ... " || goto x 418 | call a msgOrFailAt 2 "[x]" || goto x 419 | call a sha1At 2 sha1Fnv1a128 420 | call a checkFsBaseNo "Fnv1a128.1.0.0/Fnv1a128.nuspec" || goto x 421 | call a completeTest 422 | ::_____________________________________________________ 423 | 424 | 425 | ::_______ ------ ______________________________________ 426 | 427 | echo ^>%config% 428 | echo ^>>%config% 429 | echo ^>>%config% 430 | echo ^>>%config% 431 | 432 | call a startTest "/p:ngconfig=`%config%`" || goto x 433 | call a msgOrFailAt 1 "Fnv1a128/1.0.0 ... " || goto x 434 | call a msgOrFailAt 2 "!sha1Fnv1a128! ... !sha1Fnv1a128!" || goto x 435 | call a checkFsBase "Fnv1a128.1.0.0" "Fnv1a128.nuspec" || goto x 436 | call a completeTest 437 | ::_____________________________________________________ 438 | 439 | 440 | ::_______ ------ ______________________________________ 441 | 442 | call a unsetNupkg "%basePkgDir%Huid.nupkg" 443 | 444 | call a startTest "Huid?cccccccccccccccccccccccccccccccccccccccc:Huid.nupkg /t:grab" 1 || goto x 445 | call a msgOrFailAt 1 "Huid ... " || goto x 446 | call a msgOrFailAt 2 "[x]" || goto x 447 | call a checkFsNupkg "%basePkgDir%Huid.nupkg" || goto x 448 | call a completeTest 449 | ::_____________________________________________________ 450 | 451 | 452 | ::::::::::::: 453 | call :cleanup 454 | 455 | :::::::::::::::::: :::::::::::::: ::::::::::::::::::::::::: 456 | :: 457 | :x 458 | endlocal & set /a %1=%gcount% & set /a %2=%failedTotal% 459 | if !failedTotal! EQU 0 exit /B 0 460 | exit /B 1 461 | 462 | :cleanup 463 | call a unsetPackage 464 | call a unsetFile %config% 465 | call a unsetDir %artefactsDirName% 466 | exit /B 0 -------------------------------------------------------------------------------- /vsSolutionBuildEvent.bat: -------------------------------------------------------------------------------- 1 | :: Visual Studio IDE plugin: https://github.com/3F/vsSolutionBuildEvent/releases/latest 2 | @.tools\hMSBuild ~x -GetNuTool vsSolutionBuildEvent & if "%~1"=="" packages\vsSolutionBuildEvent\GUI --------------------------------------------------------------------------------