src/build/BullseyeTargets/UnpackPackageTarget.cs (50 lines of code) (raw):

using System; using System.IO; using System.Linq; using System.Threading.Tasks; using ElastiBuild.Extensions; using Ionic.Zip; namespace ElastiBuild.BullseyeTargets { public class UnpackPackageTarget : BullseyeTargetBase<UnpackPackageTarget> { public static Task RunAsync(BuildContext ctx) { var ap = ctx.GetArtifactPackage(); var destDir = Path.Combine(ctx.InDir, Path.GetFileNameWithoutExtension(ap.FileName)); using var zf = ZipFile.Read(Path.Combine(ctx.InDir, ap.FileName)); var firstEntryPath = zf.Entries.First().FileName; var archiveRootDir = firstEntryPath .Substring(0, firstEntryPath.IndexOfAny(new[] { '/', '\\' })); bool allDirsRooted = zf.Entries .All(itm => itm.FileName.StartsWith(archiveRootDir)); if (!allDirsRooted) throw new InvalidDataException( $"Unexpected non-uniform root directory in product archive '{ap.FileName}'"); Directory.CreateDirectory(destDir); int totalItems = zf.Count; int currentItem = 0; foreach (var itm in zf.Entries) { var fname = itm.FileName.Substring(archiveRootDir.Length + 1); if (itm.IsDirectory) { Directory.CreateDirectory( Path.Combine(destDir, fname)); } else { var path = Path.Combine(destDir, fname); Directory.CreateDirectory(Path.GetDirectoryName(path)); using var fs = File.Open(path, FileMode.Create, FileAccess.Write); itm.Extract(fs); } double progress = ((++currentItem * 100.0) / totalItems); if (progress % 10 == 0) Console.WriteLine((int) progress + "%"); } Console.WriteLine($"Extracted to: {destDir}"); return Task.CompletedTask; } } }