diff --git a/.gitignore b/.gitignore index 5d40b41..b9f1c63 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +/.build/ /Library/ /Output/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..b7c9873 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,4 @@ +language: csharp + +script: + - ./build diff --git a/Apokee.Artwork.nuspec b/Apokee.Artwork.nuspec index d67f9b0..10d9a99 100644 --- a/Apokee.Artwork.nuspec +++ b/Apokee.Artwork.nuspec @@ -11,7 +11,7 @@ https://raw.githubusercontent.com/Apokee/Artwork/master/LICENSE.md - + diff --git a/CHANGES.md b/CHANGELOG.md similarity index 100% rename from CHANGES.md rename to CHANGELOG.md diff --git a/appveyor.yml b/appveyor.yml index f01d09a..016b50e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -21,16 +21,16 @@ before_build: build_script: ps: | if ($env:BUILD_RELEASE -eq "True") { - ./build -release=true + ./build --release=true } else { ./build } after_build: ps: | - $env:BUILD_VERSION = (cat Output/VERSION) - $env:BUILD_PRELEASE = (cat Output/PRELEASE) - $env:BUILD_CHANGELOG = [System.String]::Join("\n", (cat Output/CHANGELOG)) + $env:BUILD_VERSION = (cat .build/out/VERSION) + $env:BUILD_PRELEASE = (cat .build/out/PRELEASE) + $env:BUILD_CHANGELOG = [System.String]::Join("\n", (cat .build/out/CHANGELOG)) $versionMessage = "Version: $env:BUILD_VERSION" @@ -44,10 +44,10 @@ after_build: test: off artifacts: - - path: 'Output\Package\*.nupkg' + - path: '.build\out\package\*.nupkg' name: NuGetPackage - - path: 'Output\Package\*.zip' + - path: '.build\out\package\*.zip' name: ZipPackage deploy: diff --git a/build b/build new file mode 100755 index 0000000..9ed4c8b --- /dev/null +++ b/build @@ -0,0 +1,64 @@ +#!/bin/sh +set -e + +arg0="" +remainingArgs="" + +if [ $# -gt 0 ]; then + arg0="$1" +fi + +if [ $# -gt 1 ]; then + skippedFirst=false + for i in "$@"; do + if $skippedFirst; then + remainingArgs="$remainingArgs $i" + else + skippedFirst=true + fi + done +fi + +nugetVersion="4.1.0" +useExperimental=false +rootDir=$(dirname $0) +buildDir="$rootDir/.build" +toolsDir="$buildDir/tools" +packagesDir="$buildDir/lib/nuget" +nugetExe="$toolsDir/nuget/$nugetVersion/NuGet.exe" +packagesConfigFile="$rootDir/packages.config" +cakeVersion="$(sed -nE "s|\s*\s*|\1|p" $packagesConfigFile)" +cakeExe="$packagesDir/Cake.$cakeVersion/Cake.exe" + +nugetDir="$(dirname $nugetExe)" +if [ ! -d "$nugetDir" ]; then + mkdir -p "$nugetDir" +fi + +if [ ! -f "$nugetExe" ]; then + curl -L "https://dist.nuget.org/win-x86-commandline/v${nugetVersion}/nuget.exe" --output "$nugetExe" +fi + +mono "$nugetExe" install "$packagesConfigFile" -OutputDirectory "$packagesDir" + +cakeArgs="" + +if [ -n "$arg0" ]; then + case $arg0 in + -*) + cakeArgs="$cakeArgs $arg0" + ;; + *) + cakeArgs="$cakeArgs --target=$arg0" + ;; + esac +fi + +if $useExperimental; then + cakeArgs="$cakeArgs --experimental" +fi + +echo "CAKE: mono $cakeExe $cakeArgs $remainingArgs" + +mono "$cakeExe" $cakeArgs $remainingArgs +exit $? diff --git a/build.cake b/build.cake index 0efe44d..c5f6fe7 100644 --- a/build.cake +++ b/build.cake @@ -1,36 +1,54 @@ -#l "build-extra.cake" +#l "cake/build-extra.cake" -var target = Argument("target", "Package"); -var release = Argument("release", false); - -var buildConfig = GetBuildConfiguration(); +public sealed class Globals +{ + public string Target { get; set; } + public bool Release { get; set; } + public BuildConfig BuildConfig { get; set; } + public string OutputDir { get; set; } + public string OutputBuildDir { get; set; } + public string OutputPackageDir { get; set; } +} -var outputDir = System.IO.Path.Combine("Output"); -var outputBuildDir = System.IO.Path.Combine(outputDir, "Build"); -var outputPackageDir = System.IO.Path.Combine(outputDir, "Package"); +private Globals GetGlobals() +{ + var globals = new Globals(); + globals.Target = Argument("target", "Package"); + globals.Release = Argument("release", false); + globals.BuildConfig = GetBuildConfiguration(); + globals.OutputDir = System.IO.Path.Combine(".build/out"); + globals.OutputBuildDir = System.IO.Path.Combine(globals.OutputDir, "build"); + globals.OutputPackageDir = System.IO.Path.Combine(globals.OutputDir, "package"); + + return globals; +} Task("CleanBuild") .Does(() => { - CleanDirectories(new DirectoryPath[] { outputBuildDir }); + var globals = GetGlobals(); + CleanDirectories(new DirectoryPath[] { globals.OutputBuildDir }); }); Task("CleanPackage") .Does(() => { - CleanDirectories(new DirectoryPath[] { outputPackageDir }); + var globals = GetGlobals(); + CleanDirectories(new DirectoryPath[] { globals.OutputPackageDir }); }); Task("BuildVersionInfo") .Does(() => { + var globals = GetGlobals(); + SemVer buildVersion; var changeLog = GetChangeLog(); var version = changeLog.LatestVersion; var rev = GetGitRevision(useShort: true); - if (rev != null && !release) + if (rev != null && !globals.Release) { if (version.Build == null) { @@ -46,9 +64,9 @@ Task("BuildVersionInfo") buildVersion = version; } - System.IO.File.WriteAllText("Output/VERSION", buildVersion); - System.IO.File.WriteAllText("Output/PRELEASE", (buildVersion.Pre != null).ToString().ToLower()); - System.IO.File.WriteAllText("Output/CHANGELOG", changeLog.LatestChanges); + System.IO.File.WriteAllText(System.IO.Path.Combine(globals.OutputDir, "VERSION"), buildVersion); + System.IO.File.WriteAllText(System.IO.Path.Combine(globals.OutputDir, "PRELEASE"), (buildVersion.Pre != null).ToString().ToLower()); + System.IO.File.WriteAllText(System.IO.Path.Combine(globals.OutputDir, "CHANGELOG"), changeLog.LatestChanges); }); Task("Build") @@ -56,8 +74,10 @@ Task("Build") .IsDependentOn("BuildVersionInfo") .Does(() => { - Convert(buildConfig); - CopyFile("LICENSE.md", System.IO.Path.Combine(outputBuildDir, "LICENSE.md")); + var globals = GetGlobals(); + + Convert(globals.BuildConfig); + CopyFile("LICENSE.md", System.IO.Path.Combine(globals.OutputBuildDir, "LICENSE.md")); }); Task("NugetPackage") @@ -65,9 +85,11 @@ Task("NugetPackage") .IsDependentOn("Build") .Does(() => { + var globals = GetGlobals(); + NuGetPack("Apokee.Artwork.nuspec", new NuGetPackSettings { Version = GetVersion().ToString(), - OutputDirectory = outputPackageDir, + OutputDirectory = globals.OutputPackageDir, }); }); @@ -76,9 +98,11 @@ Task("ZipPackage") .IsDependentOn("Build") .Does(() => { - var packageFile = System.IO.Path.Combine(outputPackageDir, String.Format("Apokee.Artwork-{0}.zip", GetBuildVersion())); + var globals = GetGlobals(); + + var packageFile = System.IO.Path.Combine(globals.OutputPackageDir, String.Format("Apokee.Artwork-{0}.zip", GetBuildVersion())); - Zip(outputBuildDir, packageFile); + Zip(globals.OutputBuildDir, packageFile); }); Task("Package") @@ -88,9 +112,10 @@ Task("Package") { }); -RunTarget(target); +RunTarget(GetGlobals().Target); private SemVer GetBuildVersion() { - return new SemVer(System.IO.File.ReadAllText("Output/VERSION")); + var globals = GetGlobals(); + return new SemVer(System.IO.File.ReadAllText(System.IO.Path.Combine(globals.OutputDir, "VERSION"))); } diff --git a/build.ps1 b/build.ps1 index c766631..74b2c6f 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,41 +1,51 @@ -Param ( - [Parameter(Position = 0)] - [string]$Arg0, - - [Parameter(ValueFromRemainingArguments = $true)] - [Object[]]$RemainingArgs -) - -# Globals -# TODO: The experimental flag is necessary after upgrading to VS2015 until the final version of Roslyn is available -# This should presumably occur once VS2015 is final -$UseExperimental = $true -$RootDir = "$PSScriptRoot" -$PackagesConfigFile = "$RootDir/packages.config" -$PackagesDir = "$RootDir/Library/NuGet" -$CakeVersionXPath = "//package[@id='Cake'][1]/@version" -$CakeVersion = (Select-Xml -Xml ([xml](Get-Content $PackagesConfigFile)) -XPath $CakeVersionXPath).Node.Value -$CakeExe = "$PackagesDir/Cake.$CakeVersion/Cake.exe" - -# Install build packages -iex "NuGet install `"$PackagesConfigFile`" -OutputDirectory `"$PackagesDir`"" | - Select-String -NotMatch -Pattern "All packages listed in packages.config are already installed." - -# Build args -$cakeArgs = @() - -if ($Arg0) { - if ($Arg0[0] -eq "-") { - $cakeArgs += "$Arg0" - } else { - $cakeArgs += "-target=$Arg0" - } -} - -if ($UseExperimental) { - $cakeArgs += "-experimental" -} - -# Run Cake -iex "$CakeExe $cakeArgs $RemainingArgs" -exit $LASTEXITCODE +Param ( + [Parameter(Position = 0)] + [string]$Arg0, + + [Parameter(ValueFromRemainingArguments = $true)] + [Object[]]$RemainingArgs +) + +# Globals +$NugetVersion = "4.1.0" +$UseExperimental = $false +$RootDir = "${PSScriptRoot}" +$BuildDir = "${RootDir}/.build" +$ToolsDir = "${BuildDir}/tools" +$PackagesDir = "${BuildDir}/lib/nuget" +$NugetExe = "${ToolsDir}/nuget/${NugetVersion}/NuGet.exe" +$PackagesConfigFile = "${RootDir}/packages.config" +$CakeVersion = (Select-Xml -Xml ([xml](Get-Content $PackagesConfigFile)) -XPath "//package[@id='Cake'][1]/@version").Node.Value +$CakeExe = "${PackagesDir}/Cake.${CakeVersion}/Cake.exe" + +# Download NuGet +$nugetDir = Split-Path $NugetExe -Parent +if (!(Test-Path $nugetDir)) { + mkdir $nugetDir > $null +} + +if (!(Test-Path $NugetExe)) { + (New-Object System.Net.WebClient).DownloadFile("https://dist.nuget.org/win-x86-commandline/v${NugetVersion}/nuget.exe", $NugetExe) +} + +# Install build packages +iex "${NugetExe} install `"${PackagesConfigFile}`" -OutputDirectory `"${PackagesDir}`"" + +# Build args +$cakeArgs = @() + +if ($Arg0) { + if ($Arg0[0] -eq "-") { + $cakeArgs += "${Arg0}" + } else { + $cakeArgs += "--target=${Arg0}" + } +} + +if ($UseExperimental) { + $cakeArgs += "--experimental" +} + +# Run Cake +iex "${CakeExe} ${cakeArgs} ${RemainingArgs}" +exit $LASTEXITCODE diff --git a/build.yml b/build.yml index eb61882..cb574db 100644 --- a/build.yml +++ b/build.yml @@ -1,5 +1,5 @@ -input_dir: "Source" -output_dir: "Output/Build" +input_dir: "src" +output_dir: ".build/out/build" conversions: - input: Airplane.svg diff --git a/cake.config b/cake.config new file mode 100644 index 0000000..c9369de --- /dev/null +++ b/cake.config @@ -0,0 +1,4 @@ +[Paths] +Tools=./.build/tools +Addins=./.build/cake/addins +Modules=./.build/cake/modules diff --git a/build-extra.cake b/cake/build-extra.cake similarity index 68% rename from build-extra.cake rename to cake/build-extra.cake index e3511b8..a87ad54 100644 --- a/build-extra.cake +++ b/cake/build-extra.cake @@ -4,31 +4,31 @@ using YamlDotNet.Serialization; public sealed class BuildConfig { - [YamlAlias("input_dir")] + [YamlMember(Alias = "input_dir")] public string InputDir { get; set; } - [YamlAlias("output_dir")] + [YamlMember(Alias = "output_dir")] public string OutputDir { get; set; } - [YamlAlias("conversions")] + [YamlMember(Alias = "conversions")] public ConvertConfig[] Conversions { get; set; } } public sealed class ConvertConfig { - [YamlAlias("input")] + [YamlMember(Alias = "input")] public string Input { get; set; } - [YamlAlias("output")] + [YamlMember(Alias = "output")] public string Output { get; set; } - [YamlAlias("background")] + [YamlMember(Alias = "background")] public string Background { get; set; } - [YamlAlias("level_colors")] + [YamlMember(Alias = "level_colors")] public string LevelColors { get; set; } - [YamlAlias("resize")] + [YamlMember(Alias = "resize")] public string Resize { get; set; } } @@ -38,6 +38,9 @@ public void Convert(BuildConfig buildConfig) { Console.WriteLine("Converting {0} -> {1}", conversion.Input, conversion.Output); + if (!DirectoryExists(buildConfig.OutputDir)) + CreateDirectory(buildConfig.OutputDir); + Convert( System.IO.Path.Combine(buildConfig.InputDir, conversion.Input), System.IO.Path.Combine(buildConfig.OutputDir, conversion.Output), @@ -55,23 +58,19 @@ public void Convert(string inputFile, string outputFile, var arguments = new StringBuilder(); if (background != null) - { arguments.AppendFormat(" -background {0}", background); - } - if (levelColors != null) - { - arguments.AppendFormat(" +level-colors {0}", levelColors); - } + arguments.AppendFormat(" {0}", inputFile); if (resize != null) - { arguments.AppendFormat(" -resize {0}", resize); - } - arguments.AppendFormat(" {0} {1}", inputFile, outputFile); + if (levelColors != null) + arguments.AppendFormat(" -channel RGB +level-colors {0}", levelColors); + + arguments.AppendFormat(" {0}", outputFile); - var exitCode = StartProcess(Which("convert"), new ProcessSettings { Arguments = arguments.ToString() }); + var exitCode = StartProcess(Which("magick"), new ProcessSettings { Arguments = arguments.ToString() }); if (exitCode != 0) { diff --git a/utilities.cake b/cake/utilities.cake similarity index 71% rename from utilities.cake rename to cake/utilities.cake index 6e8d12f..0670779 100644 --- a/utilities.cake +++ b/cake/utilities.cake @@ -1,7 +1,6 @@ -#r "Library/NuGet/YamlDotNet.3.6.1/lib/net35/YamlDotNet.dll" +#addin "nuget:?package=Cake.Yaml&version=1.0.3.7" using System.Text.RegularExpressions; -using YamlDotNet.Serialization; public T GetBuildConfiguration() where T : new() { @@ -9,14 +8,11 @@ public T GetBuildConfiguration() where T : new() var workingDirectoryName = workingDirectorySegments[workingDirectorySegments.Length - 1]; var configFile = (new [] { "build.yml", String.Format("../{0}.build.yml", workingDirectoryName) }) - .FirstOrDefault(System.IO.File.Exists); + .Select(i => File(i)) + .Select(i => i.Path) + .FirstOrDefault(FileExists); - if (configFile == null) - { - return new T(); - } - - return new Deserializer(ignoreUnmatched: true).Deserialize(new StreamReader(configFile)); + return configFile != null ? DeserializeYamlFromFile(configFile) : new T(); } public string GetSolution() @@ -42,37 +38,41 @@ public string GetSolution() public string Which(string executable) { - var seperator = new char[] { System.Environment.OSVersion.Platform == PlatformID.Unix ? ':' : ';' }; + char[] seperators = { System.IO.Path.PathSeparator }; var envPath = Environment.GetEnvironmentVariable("PATH"); var envPathExt = Environment.GetEnvironmentVariable("PATHEXT"); var paths = envPath == null ? new string[0] : - envPath.Split(seperator, StringSplitOptions.RemoveEmptyEntries); + envPath.Split(seperators, StringSplitOptions.RemoveEmptyEntries); var pathExts = envPathExt == null ? new string[0] : - envPathExt.Split(seperator, StringSplitOptions.RemoveEmptyEntries); + envPathExt.Split(seperators, StringSplitOptions.RemoveEmptyEntries); foreach (var path in paths) { var testPath = System.IO.Path.Combine(path, executable); - if (System.IO.File.Exists(testPath)) - { - return testPath; - } - + /* We test the extensionful version first since it's not uncommon for multiplatform programs to ship with a + * Unix executable without an extension in the same directory as a Windows extension with an extension such as + * .cmd, .bat. In those cases trying to execute the extensionless version will fail on Windows. + */ foreach (var pathExt in pathExts) { var testPathExt = System.IO.Path.Combine(path, executable) + pathExt; - if (System.IO.File.Exists(testPathExt)) + if (FileExists(testPathExt)) { return testPathExt; } } + + if (FileExists(testPath)) + { + return testPath; + } } return null; @@ -88,7 +88,11 @@ public string GetGitRevision(bool useShort) var shortOption = useShort ? "--short" : ""; StartProcess(git, - new ProcessSettings { RedirectStandardOutput = true, Arguments = $"rev-parse {shortOption} HEAD"}, + new ProcessSettings + { + RedirectStandardOutput = true, + Arguments = string.Format("rev-parse {0} HEAD", shortOption) + }, out output ); @@ -113,15 +117,15 @@ public SemVer GetVersion() public ChangeLog GetChangeLog() { - return new ChangeLog("CHANGES.md"); + return new ChangeLog("CHANGELOG.md"); } public sealed class ChangeLog { private static readonly Regex VersionPattern = new Regex(@"^## v(?.+)$", RegexOptions.Compiled); - public SemVer LatestVersion { get; } - public string LatestChanges { get; } + public SemVer LatestVersion { get; private set; } + public string LatestChanges { get; private set; } public ChangeLog(string path) { @@ -172,11 +176,11 @@ public sealed class SemVer private string _string; - public uint Major { get; } - public uint Minor { get; } - public uint Patch { get; } - public string Pre { get; } - public string Build { get; } + public uint Major { get; private set; } + public uint Minor { get; private set; } + public uint Patch { get; private set; } + public string Pre { get; private set; } + public string Build { get; private set; } public SemVer(string s) { @@ -204,7 +208,7 @@ public sealed class SemVer } else { - throw new FormatException($"Unable to parse semantic version: {_string}"); + throw new FormatException(string.Format("Unable to parse semantic version: {0}", _string)); } } @@ -216,16 +220,16 @@ public sealed class SemVer Pre = pre; Build = build; - _string = $"{Major}.{Minor}.{Patch}"; + _string = string.Format("{0}.{1}.{2}", Major, Minor, Patch); if (pre != null) { - _string += $"-{Pre}"; + _string += string.Format("-{0}", Pre); } if (build != null) { - _string += $"+{Build}"; + _string += string.Format("+{0}", Build); } } diff --git a/packages.config b/packages.config index 0f5b485..a4ceec1 100644 --- a/packages.config +++ b/packages.config @@ -1,5 +1,4 @@  - - + diff --git a/Source/Airplane.svg b/src/Airplane.svg similarity index 100% rename from Source/Airplane.svg rename to src/Airplane.svg diff --git a/Source/Apokee.svg b/src/Apokee.svg similarity index 100% rename from Source/Apokee.svg rename to src/Apokee.svg diff --git a/Source/Connection.svg b/src/Connection.svg similarity index 100% rename from Source/Connection.svg rename to src/Connection.svg diff --git a/Source/HotSpot.svg b/src/HotSpot.svg similarity index 100% rename from Source/HotSpot.svg rename to src/HotSpot.svg diff --git a/Source/Ketchup.svg b/src/Ketchup.svg similarity index 100% rename from Source/Ketchup.svg rename to src/Ketchup.svg diff --git a/Source/PlaneMode.svg b/src/PlaneMode.svg similarity index 100% rename from Source/PlaneMode.svg rename to src/PlaneMode.svg diff --git a/Source/Rocket.svg b/src/Rocket.svg similarity index 100% rename from Source/Rocket.svg rename to src/Rocket.svg