Skip to content

Commit

Permalink
Merge pull request #3881 from devlead/feature/gh-3879/gh-3880
Browse files Browse the repository at this point in the history
GH3879/3880: Scope cache per script host
  • Loading branch information
devlead authored Apr 29, 2022
2 parents a5e35e5 + 43b4283 commit 08db227
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 53 deletions.
47 changes: 18 additions & 29 deletions src/Cake/Infrastructure/Scripting/RoslynScriptSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,29 +98,17 @@ public void ImportNamespace(string @namespace)
public void Execute(Script script)
{
var scriptName = _settings.Script.GetFilename();
var cacheDLLFileName = $"{scriptName}.dll";
var cacheHashFileName = $"{scriptName}.hash";
var cachedAssembly = _scriptCachePath.CombineWithFilePath(cacheDLLFileName);
var hashFile = _scriptCachePath.CombineWithFilePath(cacheHashFileName);
string scriptHash = default;
FilePath cachedAssembly = _scriptCacheEnabled
? GetCachedAssemblyPath(script, scriptName)
: default;

if (_scriptCacheEnabled && _fileSystem.Exist(cachedAssembly) && !_regenerateCache)
{
_log.Verbose($"Cache enabled: Checking cache build script ({cacheDLLFileName})");
scriptHash = FastHash.GenerateHash(Encoding.UTF8.GetBytes(string.Concat(script.Lines)));
var cachedHash = _fileSystem.Exist(hashFile)
? _fileSystem.GetFile(hashFile).ReadLines(Encoding.UTF8).FirstOrDefault()
: string.Empty;
if (scriptHash.Equals(cachedHash, StringComparison.Ordinal))
{
_log.Verbose("Running cached build script...");
RunScriptAssembly(cachedAssembly.FullPath);
return;
}
else
{
_log.Verbose("Cache check failed.");
}
_log.Verbose("Running cached build script...");
RunScriptAssembly(cachedAssembly.FullPath);
return;
}

// Generate the script code.
var generator = new RoslynCodeGenerator();
var code = generator.Generate(script);
Expand Down Expand Up @@ -205,19 +193,11 @@ public void Execute(Script script)
{
_fileSystem.GetDirectory(_scriptCachePath).Create();
}
if (string.IsNullOrWhiteSpace(scriptHash))
{
scriptHash = FastHash.GenerateHash(Encoding.UTF8.GetBytes(string.Concat(script.Lines)));
}

var emitResult = compilation.Emit(cachedAssembly.FullPath);

if (emitResult.Success)
{
using (var stream = _fileSystem.GetFile(hashFile).OpenWrite())
using (var writer = new StreamWriter(stream, Encoding.UTF8))
{
writer.Write(scriptHash);
}
RunScriptAssembly(cachedAssembly.FullPath);
}
}
Expand All @@ -227,6 +207,15 @@ public void Execute(Script script)
}
}

private FilePath GetCachedAssemblyPath(Script script, FilePath scriptName)
=> _scriptCachePath.CombineWithFilePath(
string.Join(
'.',
scriptName.GetFilenameWithoutExtension().FullPath,
_host.GetType().Name,
FastHash.GenerateHash(Encoding.UTF8.GetBytes(string.Concat(script.Lines))),
"dll"));

private void RunScriptAssembly(string assemblyPath)
{
var assembly = _loader.Load(assemblyPath, false);
Expand Down
58 changes: 34 additions & 24 deletions tests/integration/Cake/ScriptCache.cake
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,17 @@ using System.Diagnostics;
public class ScriptCacheData
{
public FilePath ScriptPath { get; }
public FilePath ScriptCacheAssemblyPath { get; }
public FilePath ScriptCacheHashPath { get; }
public GlobPattern ScriptCacheAssemblyPattern { get; }
public FilePath ConfigScriptPath { get; }
public DirectoryPath ConfigScriptCachePath { get; }
public FilePath ConfigScriptCacheAssemblyPath { get; }
public FilePath ConfigScriptCacheHashPath { get; }
public GlobPattern ConfigScriptCacheAssemblyPattern { get; }
public (TimeSpan Elapsed, string Hash) CompileResult { get; set; }
public (TimeSpan Elapsed, string Hash) ExecuteResult { get; set; }
public (TimeSpan Elapsed, string Hash) ReCompileResult { get; set; }
public (TimeSpan Elapsed, string Hash) ConfigCompileResult { get; set; }
public CakeSettings Settings { get; }
private Action<FilePath, CakeSettings> CakeExecuteScript { get; }
private Func<FilePath, FileHash> CalculateFileHash { get; }
private Func<GlobPattern, FileHash> CalculateFileHash { get; }

public TimeSpan Time(Action action)
{
Expand Down Expand Up @@ -45,25 +43,35 @@ public class ScriptCacheData
scriptPath ?? ScriptPath,
Settings);
}),
CalculateFileHash(ScriptCacheAssemblyPath).ToHex()
CalculateFileHash(ScriptCacheAssemblyPattern).ToHex()
);

public ScriptCacheData(
DirectoryPath scriptDirectoryPath,
Action<FilePath, CakeSettings> cakeExecuteScript,
Func<FilePath, FileHash> calculateFileHash
Func<GlobPattern, FileHash> calculateFileHash
)
{
ScriptPath = scriptDirectoryPath.CombineWithFilePath("build.cake");
var cacheDirectoryPath = scriptDirectoryPath.Combine("tools").Combine("cache");
ScriptCacheAssemblyPath = cacheDirectoryPath.CombineWithFilePath("build.cake.dll");
ScriptCacheHashPath = cacheDirectoryPath.CombineWithFilePath("build.cake.hash");
var configScriptDirectoryPath = scriptDirectoryPath.Combine("Config");
ConfigScriptPath = configScriptDirectoryPath.CombineWithFilePath("build.cake");
var configCacheRootPath = configScriptDirectoryPath.Combine("CacheRootPath");
ConfigScriptCachePath = configCacheRootPath.Combine("cake-build").Combine("CacheLeafPath");
ConfigScriptCacheAssemblyPath = ConfigScriptCachePath.CombineWithFilePath("build.cake.dll");
ConfigScriptCacheHashPath = ConfigScriptCachePath.CombineWithFilePath("build.cake.hash");

ScriptPath = scriptDirectoryPath
.CombineWithFilePath("build.cake");
ScriptCacheAssemblyPattern = scriptDirectoryPath
.Combine("tools")
.Combine("cache")
.CombineWithFilePath($"build.BuildScriptHost.*.dll")
.FullPath;

ConfigScriptPath = configScriptDirectoryPath
.CombineWithFilePath("build.cake");
ConfigScriptCachePath = configCacheRootPath
.Combine("cake-build")
.Combine("CacheLeafPath");
ConfigScriptCacheAssemblyPattern = ConfigScriptCachePath
.CombineWithFilePath($"build.BuildScriptHost.*.dll")
.FullPath;

Settings = new CakeSettings {
EnvironmentVariables = new Dictionary<string, string> {
{ "CAKE_SETTINGS_ENABLESCRIPTCACHE", "true" },
Expand All @@ -79,11 +87,13 @@ public class ScriptCacheData

Setup(context =>
new ScriptCacheData(
Paths.Temp
.Combine("./Cake/ScriptCache"),
context.CakeExecuteScript,
context.CalculateFileHash
));
Paths
.Temp
.Combine("./Cake/ScriptCache"),
context.CakeExecuteScript,
globberPattern => context.CalculateFileHash(context.GetFiles(globberPattern).OrderByDescending(file => System.IO.File.GetLastWriteTime(file.FullPath)).FirstOrDefault())
)
);

Task("Cake.ScriptCache.Setup")
.Does(() =>
Expand Down Expand Up @@ -111,8 +121,8 @@ Task("Cake.ScriptCache.Compile")
data.CompileResult = data.TimeCakeExecuteScript();

// Then
Assert.True(FileExists(data.ScriptCacheAssemblyPath), $"Script Cache Assembly Path {data.ScriptCacheAssemblyPath} missing.");
Assert.True(FileExists(data.ScriptCacheHashPath), $"Script Cache Hash Path {data.ScriptCacheHashPath} missing.");
var count = GetFiles(data.ScriptCacheAssemblyPattern).Count();
Assert.True(1 == count, $"Script Cache Assembly Path {data.ScriptCacheAssemblyPattern.Pattern} expected 1 got {count}.");
});

var scriptCacheExecute = Task("Cake.ScriptCache.Execute");
Expand Down Expand Up @@ -149,8 +159,8 @@ Task("Cake.ScriptCache.Config")
data.ConfigCompileResult = data.TimeCakeExecuteScript(data.ConfigScriptPath);

// Then
Assert.True(FileExists(data.ConfigScriptCacheAssemblyPath), $"Script Cache Assembly Path {data.ConfigScriptCacheAssemblyPath} missing.");
Assert.True(FileExists(data.ConfigScriptCacheHashPath), $"Script Cache Hash Path {data.ConfigScriptCacheHashPath} missing.");
var count = GetFiles(data.ConfigScriptCacheAssemblyPattern).Count();
Assert.True(1 == count, $"Script Cache Assembly Path {data.ConfigScriptCacheAssemblyPattern.Pattern} expected 1 got {count}.");
});

Task("Cake.ScriptCache")
Expand Down

0 comments on commit 08db227

Please sign in to comment.