public void Compress_DirTemplate(string arcType, string srcDirPath, string destArc, ArchiveHelper.CompressLevel level, string encodingStr = null) { // Compress,<ArchiveType>,<SrcPath>,<DestArchive>,[CompressLevel],[UTF8|UTF16|UTF16BE|ANSI] EngineState s = EngineTests.CreateEngineState(); string dirPath = StringEscaper.Preprocess(s, Path.Combine("%TestBench%", "CommandArchive")); string destRootDir = Path.Combine(dirPath, "Compress_Dest"); string destFullPath = Path.Combine(destRootDir, destArc); string compRootDir = Path.Combine(dirPath, "Compress_Comp"); string compDir = Path.Combine(compRootDir, destArc); string srcFullPath = Path.Combine(dirPath, srcDirPath); try { Directory.CreateDirectory(destRootDir); Directory.CreateDirectory(compDir); string rawCode = $"Compress,{arcType},\"%TestBench%\\CommandArchive\\{srcDirPath}\",\"%TestBench%\\CommandArchive\\Compress_Dest\\{destArc}\""; if (encodingStr != null) { rawCode += "," + encodingStr; } EngineTests.Eval(s, rawCode, CodeType.Compress, ErrorCheck.Success, out CodeCommand cmd); Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_Compress)); CodeInfo_Compress info = cmd.Info as CodeInfo_Compress; ArchiveHelper.DecompressManaged(destFullPath, compDir, true, info.Encoding); string[] srcFiles = Directory.GetFiles(srcFullPath, "*", SearchOption.AllDirectories); string[] destFiles = Directory.GetFiles(compDir, "*", SearchOption.AllDirectories); Assert.IsTrue(srcFiles.Length == destFiles.Length); for (int i = 0; i < srcFiles.Length; i++) { using (FileStream srcStream = new FileStream(srcFiles[i], FileMode.Open, FileAccess.Read, FileShare.Read)) using (FileStream destStream = new FileStream(destFiles[i], FileMode.Open, FileAccess.Read, FileShare.Read)) { byte[] srcDigest = HashHelper.CalcHash(HashType.SHA256, srcStream); byte[] destDigest = HashHelper.CalcHash(HashType.SHA256, destStream); Assert.IsTrue(srcDigest.SequenceEqual(destDigest)); } } } finally { Directory.Delete(destRootDir, true); Directory.Delete(compRootDir, true); } }
public static List <LogInfo> Compress(EngineState s, CodeCommand cmd) { List <LogInfo> logs = new List <LogInfo>(); CodeInfo_Compress info = cmd.Info.Cast <CodeInfo_Compress>(); #region Event Handlers void ReportCompressProgress(object sender, ProgressEventArgs e) { s.MainViewModel.BuildCommandProgressValue = e.PercentDone; s.MainViewModel.BuildCommandProgressText = $"Compressing... ({e.PercentDone}%)"; } #endregion // Parse arguments / parameters string srcPath = StringEscaper.Preprocess(s, info.SrcPath); string destArchive = StringEscaper.Preprocess(s, info.DestArchive); SevenZip.OutArchiveFormat outFormat = ArchiveFile.ToSevenZipOutFormat(info.Format); SevenZip.CompressionLevel compLevel = SevenZip.CompressionLevel.Normal; if (info.CompressLevel is ArchiveFile.CompressLevel level) { try { compLevel = ArchiveFile.ToSevenZipLevel(level); } catch (ArgumentException) { // Should have been filtered by CodeParser logs.Add(new LogInfo(LogState.CriticalError, $"Invalid ArchiveHelper.CompressLevel [{info.CompressLevel}]")); return(logs); } } // Path Security Check if (!StringEscaper.PathSecurityCheck(destArchive, out string errorMsg)) { return(LogInfo.LogErrorMessage(logs, errorMsg)); } // Check if a file or directory exist under name of destArchive bool appendMode = false; if (Directory.Exists(destArchive)) { return(LogInfo.LogErrorMessage(logs, $"[{destArchive}] should be a file, not a directory")); } if (File.Exists(destArchive)) { logs.Add(new LogInfo(LogState.Overwrite, $"Archive [{destArchive}] will be appended")); appendMode = true; } // If parent directory of destArchive does not exist, create it Directory.CreateDirectory(FileHelper.GetDirNameEx(destArchive)); // Prepare SevenZipSharp compressor SevenZipCompressor compressor = new SevenZipCompressor { ArchiveFormat = outFormat, CompressionMode = appendMode ? CompressionMode.Append : CompressionMode.Create, CompressionLevel = compLevel, }; // Set filename encoding to UTF-8 // 7z files always use Unicode filename, so no action is required. switch (outFormat) { case OutArchiveFormat.Zip: compressor.CustomParameters["cu"] = "on"; // Force UTF-8 for filename break; } string wildcard = Path.GetFileName(srcPath); if (!StringHelper.IsWildcard(wildcard)) { // No wildcard if (File.Exists(srcPath)) { // Compressor Options compressor.DirectoryStructure = false; // Compressor Callbacks compressor.Compressing += ReportCompressProgress; s.MainViewModel.SetBuildCommandProgress("Compress Progress"); try { compressor.CompressFiles(destArchive, srcPath); } finally { compressor.Compressing -= ReportCompressProgress; s.MainViewModel.ResetBuildCommandProgress(); } } else if (Directory.Exists(srcPath)) { // Compressor Options compressor.DirectoryStructure = true; compressor.PreserveDirectoryRoot = true; compressor.IncludeEmptyDirectories = true; // Compressor Callbacks compressor.Compressing += ReportCompressProgress; s.MainViewModel.SetBuildCommandProgress("Compress Progress"); try { compressor.CompressDirectory(srcPath, destArchive); } finally { compressor.Compressing -= ReportCompressProgress; s.MainViewModel.ResetBuildCommandProgress(); } } else { return(LogInfo.LogErrorMessage(logs, $"Cannot find [{srcPath}]")); } if (File.Exists(destArchive)) { logs.Add(new LogInfo(LogState.Success, $"[{srcPath}] compressed to [{destArchive}]")); } else { logs.Add(new LogInfo(LogState.Error, $"Compressing to [{srcPath}] failed")); } } else { // With wildcard string srcDirToFind = Path.GetDirectoryName(srcPath); string[] files = FileHelper.GetFilesEx(srcDirToFind, wildcard, SearchOption.AllDirectories); // Compressor Options compressor.DirectoryStructure = true; compressor.PreserveDirectoryRoot = true; compressor.IncludeEmptyDirectories = true; // Compressor Callbacks compressor.Compressing += ReportCompressProgress; s.MainViewModel.SetBuildCommandProgress("Compress Progress"); try { compressor.CompressFiles(destArchive, files); foreach (string f in files) { logs.Add(new LogInfo(LogState.Success, $"Compressed [{f}]")); } } finally { compressor.Compressing -= ReportCompressProgress; s.MainViewModel.ResetBuildCommandProgress(); } if (File.Exists(destArchive)) { logs.Add(new LogInfo(LogState.Success, $"[{files.Length}] files compressed to [{destArchive}]")); } else { logs.Add(new LogInfo(LogState.Error, $"Compressing to [{srcPath}] failed")); } } return(logs); }
public static List <LogInfo> Compress(EngineState s, CodeCommand cmd) { // Compress,<ArchiveType>,<SrcPath>,<DestArchive>,[CompressLevel],[UTF8|UTF16|UTF16BE|ANSI] List <LogInfo> logs = new List <LogInfo>(); Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_Compress)); CodeInfo_Compress info = cmd.Info as CodeInfo_Compress; ArchiveCompressFormat arcType = info.Format; string srcPath = StringEscaper.Preprocess(s, info.SrcPath); string destArchive = StringEscaper.Preprocess(s, info.DestArchive); ArchiveHelper.CompressLevel compLevel = ArchiveHelper.CompressLevel.Normal; if (info.CompressLevel != null) { compLevel = (ArchiveHelper.CompressLevel)info.CompressLevel; } Encoding encoding = info.Encoding; if (info.Encoding == null) { encoding = Encoding.UTF8; } // Path Security Check if (StringEscaper.PathSecurityCheck(destArchive, out string errorMsg) == false) { logs.Add(new LogInfo(LogState.Error, errorMsg)); return(logs); } if (Directory.Exists(destArchive)) { logs.Add(new LogInfo(LogState.Error, $"[{destArchive}] should be a file, not a directory")); return(logs); } else { if (File.Exists(destArchive)) { logs.Add(new LogInfo(LogState.Warning, $"File [{destArchive}] will be overwritten")); } } if (!Directory.Exists(srcPath) && !File.Exists(srcPath)) { logs.Add(new LogInfo(LogState.Error, $"Cannot find [{srcPath}]")); return(logs); } bool success; switch (arcType) { case ArchiveCompressFormat.Zip: success = ArchiveHelper.CompressManagedZip(srcPath, destArchive, compLevel, encoding); break; default: logs.Add(new LogInfo(LogState.Error, $"Compressing to [{arcType}] format is not supported")); return(logs); } if (success) { logs.Add(new LogInfo(LogState.Success, $"[{srcPath}] compressed to [{destArchive}]")); } else { logs.Add(new LogInfo(LogState.Error, $"Compressing [{srcPath}] failed")); } return(logs); }