├── .config
└── dotnet-tools.json
├── .gitattributes
├── .github
└── dependabot.yml
├── .gitignore
├── .octopus
├── channels.ocl
├── deployment_process.ocl
├── deployment_settings.ocl
└── schema_version.ocl
├── GitVersion.yml
├── LICENSE.txt
├── NuGet.Config
├── README.md
├── build.cake
├── build.cmd
├── build.ps1
├── build.sh
├── global.json
├── source
├── Octostache.Tests
│ ├── BaseFixture.cs
│ ├── CalculationFixture.cs
│ ├── ConditionalsFixture.cs
│ ├── ExtensionFixture.cs
│ ├── FiltersFixture.cs
│ ├── ItemCacheFixture.cs
│ ├── IterationFixture.cs
│ ├── JsonFixture.cs
│ ├── Octostache.Tests.csproj
│ ├── ParserFixture.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── UsageFixture.cs
│ └── VersionFixture.cs
├── Octostache.sln
├── Octostache.sln.DotSettings
└── Octostache
│ ├── CustomStringParsers
│ └── JsonParser.cs
│ ├── NullableReferenceTypeAttributes.cs
│ ├── Octostache.csproj
│ ├── Octostache.nuspec
│ ├── Properties
│ └── AssemblyInfo.cs
│ ├── Templates
│ ├── AnalysisContext.cs
│ ├── Binding.cs
│ ├── BuiltInFunctions.cs
│ ├── CalculationToken.cs
│ ├── ConditionalToken.cs
│ ├── Constants.cs
│ ├── ContentExpression.cs
│ ├── DependencyWildcard.cs
│ ├── EvaluationContext.cs
│ ├── FunctionCallExpression.cs
│ ├── Functions
│ │ ├── DateFunction.cs
│ │ ├── FormatFunction.cs
│ │ ├── HashFunction.cs
│ │ ├── NullFunction.cs
│ │ ├── TextCaseFunction.cs
│ │ ├── TextComparisonFunctions.cs
│ │ ├── TextEscapeFunctions.cs
│ │ ├── TextManipulationFunction.cs
│ │ ├── TextReplaceFunction.cs
│ │ ├── TextSubstringFunction.cs
│ │ └── VersionParseFunction.cs
│ ├── IInputToken.cs
│ ├── Identifier.cs
│ ├── Indexer.cs
│ ├── ItemCache.cs
│ ├── PropertyListBinder.cs
│ ├── RecursiveDefinitionException.cs
│ ├── RepetitionToken.cs
│ ├── SubstitutionToken.cs
│ ├── SymbolExpression.cs
│ ├── SymbolExpressionStep.cs
│ ├── Template.cs
│ ├── TemplateAnalyzer.cs
│ ├── TemplateEvaluator.cs
│ ├── TemplateParser.cs
│ ├── TemplateToken.cs
│ └── TextToken.cs
│ ├── VariableDictionary.cs
│ └── VariablesFileFormatter.cs
└── tools
└── packages.config
/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "gitversion.tool": {
6 | "version": "6.0.4",
7 | "commands": [
8 | "dotnet-gitversion"
9 | ]
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "nuget"
4 | directory: "/source/"
5 | schedule:
6 | interval: "daily"
7 | time: "09:00"
8 | timezone: "Pacific/Auckland"
9 | open-pull-requests-limit: 2
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | build/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studo 2015 cache/options directory
26 | .vs/
27 |
28 | # MSTest test Results
29 | [Tt]est[Rr]esult*/
30 | [Bb]uild[Ll]og.*
31 |
32 | # NUNIT
33 | *.VisualState.xml
34 | TestResult.xml
35 |
36 | # Build Results of an ATL Project
37 | [Dd]ebugPS/
38 | [Rr]eleasePS/
39 | dlldata.c
40 |
41 | *_i.c
42 | *_p.c
43 | *_i.h
44 | *.ilk
45 | *.meta
46 | *.obj
47 | *.pch
48 | *.pdb
49 | *.pgc
50 | *.pgd
51 | *.rsp
52 | *.sbr
53 | *.tlb
54 | *.tli
55 | *.tlh
56 | *.tmp
57 | *.tmp_proj
58 | *.log
59 | *.vspscc
60 | *.vssscc
61 | .builds
62 | *.pidb
63 | *.svclog
64 | *.scc
65 |
66 | # Chutzpah Test files
67 | _Chutzpah*
68 |
69 | # Visual C++ cache files
70 | ipch/
71 | *.aps
72 | *.ncb
73 | *.opensdf
74 | *.sdf
75 | *.cachefile
76 |
77 | # Visual Studio profiler
78 | *.psess
79 | *.vsp
80 | *.vspx
81 |
82 | # TFS 2012 Local Workspace
83 | $tf/
84 |
85 | # Guidance Automation Toolkit
86 | *.gpState
87 |
88 | # ReSharper is a .NET coding add-in
89 | _ReSharper*/
90 | *.[Rr]e[Ss]harper
91 | *.DotSettings.user
92 |
93 | # JustCode is a .NET coding addin-in
94 | .JustCode
95 |
96 | # TeamCity is a build add-in
97 | _TeamCity*
98 |
99 | # DotCover is a Code Coverage Tool
100 | *.dotCover
101 |
102 | # NCrunch
103 | _NCrunch_*
104 | .*crunch*.local.xml
105 |
106 | # MightyMoose
107 | *.mm.*
108 | AutoTest.Net/
109 |
110 | # Web workbench (sass)
111 | .sass-cache/
112 |
113 | # Installshield output folder
114 | [Ee]xpress/
115 |
116 | # DocProject is a documentation generator add-in
117 | DocProject/buildhelp/
118 | DocProject/Help/*.HxT
119 | DocProject/Help/*.HxC
120 | DocProject/Help/*.hhc
121 | DocProject/Help/*.hhk
122 | DocProject/Help/*.hhp
123 | DocProject/Help/Html2
124 | DocProject/Help/html
125 |
126 | # Click-Once directory
127 | publish/
128 |
129 | # Publish Web Output
130 | *.[Pp]ublish.xml
131 | *.azurePubxml
132 | # TODO: Comment the next line if you want to checkin your web deploy settings
133 | # but database connection strings (with potential passwords) will be unencrypted
134 | *.pubxml
135 | *.publishproj
136 |
137 | # NuGet Packages
138 | *.nupkg
139 | # The packages folder can be ignored because of Package Restore
140 | **/packages/*
141 | # except build/, which is used as an MSBuild target.
142 | !**/packages/build/
143 | # Uncomment if necessary however generally it will be regenerated when needed
144 | #!**/packages/repositories.config
145 |
146 | # Windows Azure Build Output
147 | csx/
148 | *.build.csdef
149 |
150 | # Windows Store app package directory
151 | AppPackages/
152 |
153 | # Others
154 | *.[Cc]ache
155 | ClientBin/
156 | [Ss]tyle[Cc]op.*
157 | ~$*
158 | *~
159 | *.dbmdl
160 | *.dbproj.schemaview
161 | *.pfx
162 | *.publishsettings
163 | node_modules/
164 | bower_components/
165 |
166 | # RIA/Silverlight projects
167 | Generated_Code/
168 |
169 | # Backup & report files from converting an old project file
170 | # to a newer Visual Studio version. Backup files are not needed,
171 | # because we have git ;-)
172 | _UpgradeReport_Files/
173 | Backup*/
174 | UpgradeLog*.XML
175 | UpgradeLog*.htm
176 |
177 | # SQL Server files
178 | *.mdf
179 | *.ldf
180 |
181 | # Business Intelligence projects
182 | *.rdl.data
183 | *.bim.layout
184 | *.bim_*.settings
185 |
186 | # Microsoft Fakes
187 | FakesAssemblies/
188 |
189 | # Node.js Tools for Visual Studio
190 | .ntvs_analysis.dat
191 |
192 | # Visual Studio 6 build log
193 | *.plg
194 |
195 | # Visual Studio 6 workspace options file
196 | *.opt
197 | project.lock.json
198 | tools/
199 |
200 | # Include the cake packages.config
201 | !tools/packages.config
202 |
203 | # Rider
204 | .idea/
205 |
--------------------------------------------------------------------------------
/.octopus/channels.ocl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OctopusDeploy/Octostache/f906f440a154818402b98fe85711d6d787581ea4/.octopus/channels.ocl
--------------------------------------------------------------------------------
/.octopus/deployment_process.ocl:
--------------------------------------------------------------------------------
1 | step "Approval Required" {
2 |
3 | action {
4 | action_type = "Octopus.Manual"
5 | environments = ["Components - External"]
6 | properties = {
7 | Octopus.Action.Manual.BlockConcurrentDeployments = "False"
8 | Octopus.Action.Manual.Instructions = "Please approve release before it is promoted to NuGet"
9 | }
10 | worker_pool_variable = ""
11 | }
12 | }
13 |
14 | step "NuGet Push" {
15 |
16 | action {
17 | properties = {
18 | NuGetPush.ApiKey = "#{NugetApiKey}"
19 | NuGetPush.Source.Package = "{\"PackageId\":\"Octostache\",\"FeedId\":\"Octopus Server (built-in)\"}"
20 | NuGetPush.Target.Url = "#{NugetUrl}"
21 | Octopus.Action.Template.Id = "ActionTemplates-1241"
22 | Octopus.Action.Template.Version = "0"
23 | }
24 | worker_pool = "Hosted Ubuntu"
25 |
26 | packages "NuGetPush.Source.Package" {
27 | acquisition_location = "Server"
28 | feed = "Octopus Server (built-in)"
29 | package_id = "Octostache"
30 | properties = {
31 | Extract = "False"
32 | PackageParameterName = "NuGetPush.Source.Package"
33 | SelectionMode = "deferred"
34 | }
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/.octopus/deployment_settings.ocl:
--------------------------------------------------------------------------------
1 | connectivity_policy {
2 | }
3 |
4 | versioning_strategy {
5 |
6 | donor_package {
7 | package = "NuGetPush.Source.Package"
8 | step = "NuGet Push"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/.octopus/schema_version.ocl:
--------------------------------------------------------------------------------
1 | version = 3
--------------------------------------------------------------------------------
/GitVersion.yml:
--------------------------------------------------------------------------------
1 | mode: ContinuousDeployment
2 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) Octopus Deploy and contributors. All rights reserved.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | these files except in compliance with the License. You may obtain a copy of the
5 | License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software distributed
10 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | specific language governing permissions and limitations under the License.
13 |
--------------------------------------------------------------------------------
/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Octostache is the variable substitution syntax for Octopus Deploy.
2 |
3 | Octopus allows you to [define variables](http://g.octopushq.com/DocumentationVariables), which can then be referenced from deployment steps and in scripts using the following syntax:
4 |
5 | ```
6 | #{MyVariable}
7 | ```
8 |
9 | This library contains the code for parsing and evaluating these variable expressions.
10 |
11 | Usage is simple: install **Octostache** from NuGet.org, then create a `VariableDictionary`:
12 |
13 | ```csharp
14 | var variables = new VariableDictionary();
15 | variables.Set("Server", "Web01");
16 | variables.Set("Port", "10933");
17 | variables.Set("Url", "http://#{Server | ToLower}:#{Port}");
18 |
19 | var url = variables.Get("Url"); // http://web01:10933
20 | var raw = variables.GetRaw("Url"); // http://#{Server | ToLower}:#{Port}
21 | var eval = variables.Evaluate("#{Url}/foo"); // http://web01:10933/foo
22 | ```
23 |
24 | More examples can be found in [UsageFixture](https://github.com/OctopusDeploy/Octostache/blob/master/source/Octostache.Tests/UsageFixture.cs).
25 |
26 | ## Contributing
27 | 🐙 We welcome Pull Requests ❤️🧑💻
28 |
29 | ### Code Cleanup
30 | The first stage of our CI/CD pipeline for Octostache runs a ReSharper code cleanup, to keep everything neat and tidy.
31 |
32 | Your PR won't be able to pass without ensuring the code is clean. You can do this locally via the [ReSharper CLI tools](https://www.jetbrains.com/help/rider/ReSharper_Command_Line_Tools.html), which is how we enforce it during our builds.
33 |
34 | All the formatting settings are committed to `Octostache.sln.DotSettings`, so as long as you don't override these with an `Octostache.sln.DotSettings.User` file, you should be all good.
35 |
36 | To get started with code cleanup the easiest way (via `dotnet tool`), get the CodeCleanup tool installed globally (one-time):
37 | ```
38 | dotnet tool install -g JetBrains.ReSharper.GlobalTools
39 | ```
40 | then execute the cleanup:
41 | ```
42 | jb cleanupcode ./source/Octostache.sln
43 | ```
44 |
45 | We don't try to enforce this through build scripts or pre-commit hooks, it's up to you to run when you need to. If you use the Rider IDE, it seems to apply another opinion or two when running the code cleanup, and might get different results to the CLI approach; we don't recommend cleaning up this way.
46 |
--------------------------------------------------------------------------------
/build.cake:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////
2 | // TOOLS
3 | //////////////////////////////////////////////////////////////////////
4 | #module nuget:?package=Cake.DotNetTool.Module&version=0.4.0
5 | #tool "dotnet:?package=GitVersion.Tool&version=5.12.0"
6 | #tool "nuget:?package=OctopusTools&version=9.0.0"
7 | #addin nuget:?package=Cake.Git&version=1.1.0
8 |
9 | //////////////////////////////////////////////////////////////////////
10 | // ARGUMENTS
11 | //////////////////////////////////////////////////////////////////////
12 | var target = Argument("target", "Default");
13 | var configuration = Argument("configuration", "Release");
14 |
15 | ///////////////////////////////////////////////////////////////////////////////
16 | // GLOBAL VARIABLES
17 | ///////////////////////////////////////////////////////////////////////////////
18 | var artifactsDir = "./artifacts/";
19 | var localPackagesDir = "../LocalPackages";
20 |
21 | GitVersion gitVersionInfo;
22 | string nugetVersion;
23 |
24 |
25 | ///////////////////////////////////////////////////////////////////////////////
26 | // SETUP / TEARDOWN
27 | ///////////////////////////////////////////////////////////////////////////////
28 | Setup(context =>
29 | {
30 | gitVersionInfo = GitVersion(new GitVersionSettings {
31 | OutputType = GitVersionOutput.Json
32 | });
33 |
34 | nugetVersion = gitVersionInfo.NuGetVersion;
35 |
36 | Information("Building Octostache v{0}", nugetVersion);
37 | Information("Informational Version {0}", gitVersionInfo.InformationalVersion);
38 | });
39 |
40 | Teardown(context =>
41 | {
42 | Information("Finished running tasks.");
43 | });
44 |
45 | //////////////////////////////////////////////////////////////////////
46 | // PRIVATE TASKS
47 | //////////////////////////////////////////////////////////////////////
48 |
49 | Task("Clean")
50 | .Does(() =>
51 | {
52 | CleanDirectory(artifactsDir);
53 | CleanDirectories("./source/**/bin");
54 | CleanDirectories("./source/**/obj");
55 | CleanDirectories("./source/**/TestResults");
56 | });
57 |
58 | Task("Restore")
59 | .IsDependentOn("Clean")
60 | .Does(() => {
61 | DotNetCoreRestore("source");
62 | });
63 |
64 |
65 | Task("Build")
66 | .IsDependentOn("Restore")
67 | .IsDependentOn("Clean")
68 | .Does(() =>
69 | {
70 | DotNetCoreBuild("./source", new DotNetCoreBuildSettings
71 | {
72 | Configuration = configuration,
73 | ArgumentCustomization = args => args.Append($"/p:Version={nugetVersion}")
74 | });
75 | });
76 |
77 | Task("Test")
78 | .IsDependentOn("Build")
79 | .Does(() =>
80 | {
81 | DotNetCoreTest("./source/Octostache.Tests/Octostache.Tests.csproj", new DotNetCoreTestSettings
82 | {
83 | Configuration = configuration,
84 | NoBuild = true,
85 | ArgumentCustomization = args => args.Append("-l trx")
86 | });
87 | });
88 |
89 | Task("Pack")
90 | .IsDependentOn("Test")
91 | .Does(() =>
92 | {
93 | DotNetCorePack("./source/Octostache", new DotNetCorePackSettings
94 | {
95 | Configuration = configuration,
96 | OutputDirectory = artifactsDir,
97 | NoBuild = true,
98 | ArgumentCustomization = args => args.Append($"/p:Version={nugetVersion}")
99 | });
100 |
101 | DeleteFiles(artifactsDir + "*symbols*");
102 | });
103 |
104 | Task("CopyToLocalPackages")
105 | .IsDependentOn("Pack")
106 | .WithCriteria(BuildSystem.IsLocalBuild)
107 | .Does(() =>
108 | {
109 | CreateDirectory(localPackagesDir);
110 | CopyFileToDirectory($"{artifactsDir}/Octostache.{nugetVersion}.nupkg", localPackagesDir);
111 | });
112 |
113 | Task("Default")
114 | .IsDependentOn("Pack")
115 | .IsDependentOn("CopyToLocalPackages");
116 |
117 | //////////////////////////////////////////////////////////////////////
118 | // EXECUTION
119 | //////////////////////////////////////////////////////////////////////
120 | RunTarget(target);
121 |
--------------------------------------------------------------------------------
/build.cmd:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 | REM see http://joshua.poehls.me/powershell-batch-file-wrapper/
3 |
4 | SET SCRIPTNAME=%~d0%~p0%~n0.ps1
5 | SET ARGS=%*
6 | IF [%ARGS%] NEQ [] GOTO ESCAPE_ARGS
7 |
8 | :POWERSHELL
9 | PowerShell.exe -NoProfile -NonInteractive -NoLogo -ExecutionPolicy Unrestricted -Command "& { $ErrorActionPreference = 'Stop'; & '%SCRIPTNAME%' @args; EXIT $LASTEXITCODE }" %ARGS%
10 | EXIT /B %ERRORLEVEL%
11 |
12 | :ESCAPE_ARGS
13 | SET ARGS=%ARGS:"=\"%
14 | SET ARGS=%ARGS:`=``%
15 | SET ARGS=%ARGS:'=`'%
16 | SET ARGS=%ARGS:$=`$%
17 | SET ARGS=%ARGS:{=`}%
18 | SET ARGS=%ARGS:}=`}%
19 | SET ARGS=%ARGS:(=`(%
20 | SET ARGS=%ARGS:)=`)%
21 | SET ARGS=%ARGS:,=`,%
22 | SET ARGS=%ARGS:^%=%
23 |
24 | GOTO POWERSHELL
--------------------------------------------------------------------------------
/build.ps1:
--------------------------------------------------------------------------------
1 | ##########################################################################
2 | # This is the Cake bootstrapper script for PowerShell.
3 | # This file was downloaded from https://github.com/cake-build/resources
4 | # Feel free to change this file to fit your needs.
5 | ##########################################################################
6 |
7 | <#
8 |
9 | .SYNOPSIS
10 | This is a Powershell script to bootstrap a Cake build.
11 |
12 | .DESCRIPTION
13 | This Powershell script will download NuGet if missing, restore NuGet tools (including Cake)
14 | and execute your Cake build script with the parameters you provide.
15 |
16 | .PARAMETER Script
17 | The build script to execute.
18 | .PARAMETER Target
19 | The build script target to run.
20 | .PARAMETER Configuration
21 | The build configuration to use.
22 | .PARAMETER Verbosity
23 | Specifies the amount of information to be displayed.
24 | .PARAMETER Experimental
25 | Tells Cake to use the latest Roslyn release.
26 | .PARAMETER WhatIf
27 | Performs a dry run of the build script.
28 | No tasks will be executed.
29 | .PARAMETER Mono
30 | Tells Cake to use the Mono scripting engine.
31 | .PARAMETER SkipToolPackageRestore
32 | Skips restoring of packages.
33 | .PARAMETER ScriptArgs
34 | Remaining arguments are added here.
35 |
36 | .LINK
37 | http://cakebuild.net
38 |
39 | #>
40 |
41 | [CmdletBinding()]
42 | Param(
43 | [string]$Script = "build.cake",
44 | [string]$Target = "Default",
45 | [ValidateSet("Release", "Debug")]
46 | [string]$Configuration = "Release",
47 | [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
48 | [string]$Verbosity = "Verbose",
49 | [switch]$Experimental = $true,
50 | [Alias("DryRun","Noop")]
51 | [switch]$WhatIf,
52 | [switch]$Mono,
53 | [switch]$SkipToolPackageRestore,
54 | [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
55 | [string[]]$ScriptArgs
56 | )
57 |
58 | [Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null
59 | function MD5HashFile([string] $filePath)
60 | {
61 | if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf))
62 | {
63 | return $null
64 | }
65 |
66 | [System.IO.Stream] $file = $null;
67 | [System.Security.Cryptography.MD5] $md5 = $null;
68 | try
69 | {
70 | $md5 = [System.Security.Cryptography.MD5]::Create()
71 | $file = [System.IO.File]::OpenRead($filePath)
72 | return [System.BitConverter]::ToString($md5.ComputeHash($file))
73 | }
74 | finally
75 | {
76 | if ($file -ne $null)
77 | {
78 | $file.Dispose()
79 | }
80 | }
81 | }
82 |
83 | Write-Host "Preparing to run build script..."
84 |
85 | if(!$PSScriptRoot){
86 | $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
87 | }
88 |
89 | $TOOLS_DIR = Join-Path $PSScriptRoot "tools"
90 | $NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe"
91 | $CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe"
92 | $NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
93 | $PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config"
94 | $PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum"
95 |
96 | # Should we use mono?
97 | $UseMono = "";
98 | if($Mono.IsPresent) {
99 | Write-Verbose -Message "Using the Mono based scripting engine."
100 | $UseMono = "-mono"
101 | }
102 |
103 | # Should we use the new Roslyn?
104 | $UseExperimental = "";
105 | if($Experimental.IsPresent -and !($Mono.IsPresent)) {
106 | Write-Verbose -Message "Using experimental version of Roslyn."
107 | $UseExperimental = "-experimental"
108 | }
109 |
110 | # Is this a dry run?
111 | $UseDryRun = "";
112 | if($WhatIf.IsPresent) {
113 | $UseDryRun = "-dryrun"
114 | }
115 |
116 | # Make sure tools folder exists
117 | if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) {
118 | Write-Verbose -Message "Creating tools directory..."
119 | New-Item -Path $TOOLS_DIR -Type directory | out-null
120 | }
121 |
122 | # Make sure that packages.config exist.
123 | if (!(Test-Path $PACKAGES_CONFIG)) {
124 | Write-Verbose -Message "Downloading packages.config..."
125 | try { (New-Object System.Net.WebClient).DownloadFile("http://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch {
126 | Throw "Could not download packages.config."
127 | }
128 | }
129 |
130 | # Try find NuGet.exe in path if not exists
131 | if (!(Test-Path $NUGET_EXE)) {
132 | Write-Verbose -Message "Trying to find nuget.exe in PATH..."
133 | $existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_) }
134 | $NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1
135 | if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) {
136 | Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)."
137 | $NUGET_EXE = $NUGET_EXE_IN_PATH.FullName
138 | }
139 | }
140 |
141 | # Try download NuGet.exe if not exists
142 | if (!(Test-Path $NUGET_EXE)) {
143 | Write-Verbose -Message "Downloading NuGet.exe..."
144 | try {
145 | (New-Object System.Net.WebClient).DownloadFile($NUGET_URL, $NUGET_EXE)
146 | } catch {
147 | Throw "Could not download NuGet.exe."
148 | }
149 | }
150 |
151 | # Save nuget.exe path to environment to be available to child processed
152 | $ENV:NUGET_EXE = $NUGET_EXE
153 |
154 | # Restore tools from NuGet?
155 | if(-Not $SkipToolPackageRestore.IsPresent) {
156 | Push-Location
157 | Set-Location $TOOLS_DIR
158 |
159 | # Check for changes in packages.config and remove installed tools if true.
160 | [string] $md5Hash = MD5HashFile($PACKAGES_CONFIG)
161 | if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or
162 | ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) {
163 | Write-Verbose -Message "Missing or changed package.config hash..."
164 | Remove-Item * -Recurse -Exclude packages.config,nuget.exe
165 | }
166 |
167 | Write-Verbose -Message "Restoring tools from NuGet..."
168 | $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`""
169 |
170 | if ($LASTEXITCODE -ne 0) {
171 | Throw "An error occured while restoring NuGet tools."
172 | }
173 | else
174 | {
175 | $md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII"
176 | }
177 | Write-Verbose -Message ($NuGetOutput | out-string)
178 | Pop-Location
179 | }
180 |
181 | # Make sure that Cake has been installed.
182 | if (!(Test-Path $CAKE_EXE)) {
183 | Throw "Could not find Cake.exe at $CAKE_EXE"
184 | }
185 |
186 | # We added this so we can use dotnet tools
187 | # See https://www.gep13.co.uk/blog/introducing-cake.dotnettool.module
188 | Write-Host "Installing cake modules using the --bootstrap argument"
189 | &$CAKE_EXE --bootstrap
190 |
191 | # Start Cake
192 | Write-Host "Running build script..."
193 | Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -target=`"$Target`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseMono $UseDryRun $UseExperimental $ScriptArgs"
194 | exit $LASTEXITCODE
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##########################################################################
4 | # This is the Cake bootstrapper script for Linux and OS X.
5 | # This file was downloaded from https://github.com/cake-build/resources
6 | # Feel free to change this file to fit your needs.
7 | ##########################################################################
8 |
9 | # Define directories.
10 | SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
11 | TOOLS_DIR=$SCRIPT_DIR/tools
12 | NUGET_EXE=$TOOLS_DIR/nuget.exe
13 | CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe
14 | PACKAGES_CONFIG=$TOOLS_DIR/packages.config
15 | PACKAGES_CONFIG_MD5=$TOOLS_DIR/packages.config.md5sum
16 |
17 | # Define md5sum or md5 depending on Linux/OSX
18 | MD5_EXE=
19 | if [[ "$(uname -s)" == "Darwin" ]]; then
20 | MD5_EXE="md5 -r"
21 | else
22 | MD5_EXE="md5sum"
23 | fi
24 |
25 | # Define default arguments.
26 | SCRIPT="build.cake"
27 | TARGET="Default"
28 | CONFIGURATION="Release"
29 | VERBOSITY="verbose"
30 | DRYRUN=
31 | SHOW_VERSION=false
32 | SCRIPT_ARGUMENTS=()
33 |
34 | # Parse arguments.
35 | for i in "$@"; do
36 | case $1 in
37 | -s|--script) SCRIPT="$2"; shift ;;
38 | -t|--target) TARGET="$2"; shift ;;
39 | -c|--configuration) CONFIGURATION="$2"; shift ;;
40 | -v|--verbosity) VERBOSITY="$2"; shift ;;
41 | -d|--dryrun) DRYRUN="-dryrun" ;;
42 | --version) SHOW_VERSION=true ;;
43 | --) shift; SCRIPT_ARGUMENTS+=("$@"); break ;;
44 | *) SCRIPT_ARGUMENTS+=("$1") ;;
45 | esac
46 | shift
47 | done
48 |
49 | # Make sure the tools folder exist.
50 | if [ ! -d "$TOOLS_DIR" ]; then
51 | mkdir "$TOOLS_DIR"
52 | fi
53 |
54 | # Make sure that packages.config exist.
55 | if [ ! -f "$TOOLS_DIR/packages.config" ]; then
56 | echo "Downloading packages.config..."
57 | curl -Lsfo "$TOOLS_DIR/packages.config" http://cakebuild.net/download/bootstrapper/packages
58 | if [ $? -ne 0 ]; then
59 | echo "An error occured while downloading packages.config."
60 | exit 1
61 | fi
62 | fi
63 |
64 | # Download NuGet if it does not exist.
65 | if [ ! -f "$NUGET_EXE" ]; then
66 | echo "Downloading NuGet..."
67 | curl -Lsfo "$NUGET_EXE" https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
68 | if [ $? -ne 0 ]; then
69 | echo "An error occured while downloading nuget.exe."
70 | exit 1
71 | fi
72 | fi
73 |
74 | # Restore tools from NuGet.
75 | pushd "$TOOLS_DIR" >/dev/null
76 | if [ ! -f $PACKAGES_CONFIG_MD5 ] || [ "$( cat $PACKAGES_CONFIG_MD5 | sed 's/\r$//' )" != "$( $MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' )" ]; then
77 | find . -type d ! -name . | xargs rm -rf
78 | fi
79 |
80 | mono "$NUGET_EXE" install -ExcludeVersion
81 | if [ $? -ne 0 ]; then
82 | echo "Could not restore NuGet packages."
83 | exit 1
84 | fi
85 |
86 | $MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' >| $PACKAGES_CONFIG_MD5
87 |
88 | popd >/dev/null
89 |
90 | # Make sure that Cake has been installed.
91 | if [ ! -f "$CAKE_EXE" ]; then
92 | echo "Could not find Cake.exe at '$CAKE_EXE'."
93 | exit 1
94 | fi
95 |
96 | # Start Cake
97 | if $SHOW_VERSION; then
98 | exec mono "$CAKE_EXE" -version
99 | else
100 | exec mono "$CAKE_EXE" $SCRIPT -verbosity=$VERBOSITY -configuration=$CONFIGURATION -target=$TARGET $DRYRUN "${SCRIPT_ARGUMENTS[@]}"
101 | fi
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "9.0.203",
4 | "rollForward": "latestFeature",
5 | "allowPrerelease": false
6 | }
7 | }
--------------------------------------------------------------------------------
/source/Octostache.Tests/BaseFixture.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 |
6 | namespace Octostache.Tests
7 | {
8 | public abstract class BaseFixture
9 | {
10 | protected BaseFixture()
11 | {
12 | // The TemplateParser Cache is retained between tests. A little reflection to clear it.
13 | var parser = typeof(VariableDictionary).Assembly.GetType("Octostache.Templates.TemplateParser");
14 | var clearMethod = parser?.GetMethod("ClearCache", BindingFlags.NonPublic | BindingFlags.Static);
15 | clearMethod?.Invoke(null, new object[] { });
16 | }
17 |
18 | protected string Evaluate(string template, IDictionary variables, bool haltOnError = true)
19 | {
20 | var dictionary = new VariableDictionary();
21 | foreach (var pair in variables)
22 | {
23 | dictionary[pair.Key] = pair.Value;
24 | }
25 |
26 | return dictionary.Evaluate(template, out _, haltOnError);
27 | }
28 |
29 | protected bool EvaluateTruthy(string template, IDictionary variables)
30 | {
31 | var dictionary = new VariableDictionary();
32 | foreach (var pair in variables)
33 | {
34 | dictionary[pair.Key] = pair.Value;
35 | }
36 |
37 | return dictionary.EvaluateTruthy(template);
38 | }
39 |
40 | protected VariableDictionary ParseVariables(string variableDefinitions)
41 | {
42 | var variables = new VariableDictionary();
43 |
44 | var items = variableDefinitions.Split(';');
45 | foreach (var item in items)
46 | {
47 | var pair = item.Split('=');
48 | var key = pair.First();
49 | var value = pair.Last();
50 | variables[key] = value;
51 | }
52 |
53 | return variables;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/source/Octostache.Tests/CalculationFixture.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Globalization;
4 | using FluentAssertions;
5 | using Xunit;
6 |
7 | namespace Octostache.Tests
8 | {
9 | public class CalculationFixture : BaseFixture
10 | {
11 | [Theory]
12 | [MemberData(nameof(ConditionalIsSupportedData))]
13 | public void ConditionalIsSupported(string expression, string expectedResult)
14 | {
15 | var result = Evaluate($"#{{calc {expression}}}",
16 | new Dictionary
17 | {
18 | { "A", "5" },
19 | { "B", "7" },
20 | { "The/Var", "9" },
21 | { "Another-Var", "11" },
22 | });
23 |
24 | result.Should().Be(expectedResult);
25 | }
26 |
27 | public static IEnumerable