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);
            }
        }
Example #2
0
        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);
        }
Example #3
0
        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);
        }