public static void ProcessScala( FunctionItem function, bool skipCompile, bool noAssemblyValidation, string gitSha, string gitBranch, string buildConfiguration, string outputDirectory, HashSet <string> existingPackages, string gitInfoFilename, ModuleBuilder builder ) { var showOutput = Settings.VerboseLevel >= VerboseLevel.Detailed; var scalaOutputJar = ScalaPackager.Process(function, skipCompile, noAssemblyValidation, gitSha, gitBranch, buildConfiguration, showOutput); // compute hash for zip contents string hash; using (var zipArchive = ZipFile.OpenRead(scalaOutputJar)) { using (var md5 = MD5.Create()) using (var hashStream = new CryptoStream(Stream.Null, md5, CryptoStreamMode.Write)) { foreach (var entry in zipArchive.Entries.OrderBy(e => e.FullName)) { // hash file path var filePathBytes = Encoding.UTF8.GetBytes(entry.FullName.Replace('\\', '/')); hashStream.Write(filePathBytes, 0, filePathBytes.Length); // hash file contents using (var stream = entry.Open()) { stream.CopyTo(hashStream); } } hashStream.FlushFinalBlock(); hash = md5.Hash.ToHexString(); } } // rename function package with hash var package = Path.Combine(outputDirectory, $"function_{function.Name}_{hash}.jar"); if (!existingPackages.Remove(package)) { File.Move(scalaOutputJar, package); // add git-info.json file using (var zipArchive = ZipFile.Open(package, ZipArchiveMode.Update)) { var entry = zipArchive.CreateEntry(gitInfoFilename); // Set RW-R--R-- permissions attributes on non-Windows operating system if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { entry.ExternalAttributes = 0b1_000_000_110_100_100 << 16; } using (var stream = entry.Open()) { stream.Write(Encoding.UTF8.GetBytes(JObject.FromObject(new ModuleManifestGitInfo { SHA = gitSha, Branch = gitBranch }).ToString(Formatting.None))); } } } else { File.Delete(scalaOutputJar); } // decompress project zip into temporary folder so we can add the 'GITSHAFILE' files builder.AddAsset($"{function.FullName}::PackageName", package); }