Переглянути джерело

add exclude folders argument.

Justin 3 роки тому
батько
коміт
338acc91f3

+ 173 - 19
PackTool/Program.cs

@@ -1,10 +1,146 @@
-using System.Diagnostics;
+using System.Buffers;
+using System.Diagnostics;
 using System.IO.Compression;
 
 namespace PackTool
 {
+    internal static partial class ZipFileUtils
+    {
+        // Per the .ZIP File Format Specification 4.4.17.1 all slashes should be forward slashes
+        private const char PathSeparatorChar = '/';
+        private const string PathSeparatorString = "/";
+
+        public static string EntryFromPath(string entry, int offset, int length, ref char[] buffer, bool appendPathSeparator = false)
+        {
+            Debug.Assert(length <= entry.Length - offset);
+            Debug.Assert(buffer != null);
+
+            // Remove any leading slashes from the entry name:
+            while (length > 0)
+            {
+                if (entry[offset] != Path.DirectorySeparatorChar &&
+                    entry[offset] != Path.AltDirectorySeparatorChar)
+                    break;
+
+                offset++;
+                length--;
+            }
+
+            if (length == 0)
+                return appendPathSeparator ? PathSeparatorString : string.Empty;
+
+            int resultLength = appendPathSeparator ? length + 1 : length;
+            EnsureCapacity(ref buffer, resultLength);
+            entry.CopyTo(offset, buffer, 0, length);
+
+            // '/' is a more broadly recognized directory separator on all platforms (eg: mac, linux)
+            // We don't use Path.DirectorySeparatorChar or AltDirectorySeparatorChar because this is
+            // explicitly trying to standardize to '/'
+            for (int i = 0; i < length; i++)
+            {
+                char ch = buffer[i];
+                if (ch == Path.DirectorySeparatorChar || ch == Path.AltDirectorySeparatorChar)
+                    buffer[i] = PathSeparatorChar;
+            }
+
+            if (appendPathSeparator)
+                buffer[length] = PathSeparatorChar;
+
+            return new string(buffer, 0, resultLength);
+        }
+
+        public static void EnsureCapacity(ref char[] buffer, int min)
+        {
+            Debug.Assert(buffer != null);
+            Debug.Assert(min > 0);
+
+            if (buffer.Length < min)
+            {
+                int newCapacity = buffer.Length * 2;
+                if (newCapacity < min)
+                    newCapacity = min;
+
+                char[] oldBuffer = buffer;
+                buffer = ArrayPool<char>.Shared.Rent(newCapacity);
+                ArrayPool<char>.Shared.Return(oldBuffer);
+            }
+        }
+
+        public static bool IsDirEmpty(DirectoryInfo possiblyEmptyDir)
+        {
+            using (IEnumerator<string> enumerator = Directory.EnumerateFileSystemEntries(possiblyEmptyDir.FullName).GetEnumerator())
+                return !enumerator.MoveNext();
+        }
+    }
+
     class Program
     {
+        private static void CreateZipFileFromDir(string sourceDirectoryName, string destinationArchiveFileName, string[] excludeFolders)
+        {
+            sourceDirectoryName = Path.GetFullPath(sourceDirectoryName);
+            destinationArchiveFileName = Path.GetFullPath(destinationArchiveFileName);
+
+            using (ZipArchive archive = ZipFile.Open(destinationArchiveFileName, ZipArchiveMode.Create))
+            {
+                //add files and directories
+                DirectoryInfo di = new DirectoryInfo(sourceDirectoryName);
+
+                var basePath = di.FullName;
+
+                // Windows' MaxPath (260) is used as an arbitrary default capacity, as it is likely
+                // to be greater than the length of typical entry names from the file system, even
+                // on non-Windows platforms. The capacity will be increased, if needed.
+                const int DefaultCapacity = 260;
+                char[] entryNameBuffer = ArrayPool<char>.Shared.Rent(DefaultCapacity);
+
+                try
+                {
+                    foreach (FileSystemInfo file in di.EnumerateFileSystemInfos("*", SearchOption.AllDirectories))
+                    {
+                        bool exclude = false;
+                        var fileName = file.FullName.ToLower();
+                        foreach(var excludeFolder in excludeFolders)
+                        {
+                            if (fileName.StartsWith(excludeFolder))
+                            {
+                                exclude = true;
+                                break;
+                            }
+                        }
+                        if (exclude)
+                        {
+                            continue;
+                        }
+
+                        int entryNameLength = file.FullName.Length - basePath.Length;
+                        if (file is FileInfo)
+                        {
+                            // Create entry for file:
+                            string entryName = ZipFileUtils.EntryFromPath(file.FullName, basePath.Length, entryNameLength, ref entryNameBuffer);
+                            ZipFileExtensions.CreateEntryFromFile(archive, file.FullName, entryName);
+                        }
+                        else
+                        {
+                            // Entry marking an empty dir:
+                            if (file is DirectoryInfo possiblyEmpty && ZipFileUtils.IsDirEmpty(possiblyEmpty))
+                            {
+                                // FullName never returns a directory separator character on the end,
+                                // but Zip archives require it to specify an explicit directory:
+                                string entryName = ZipFileUtils.EntryFromPath(file.FullName, basePath.Length, entryNameLength, ref entryNameBuffer, appendPathSeparator: true);
+                                archive.CreateEntry(entryName);
+                            }
+                        }
+                    }  // foreach
+                }
+                finally
+                {
+                    ArrayPool<char>.Shared.Return(entryNameBuffer);
+                }
+
+            }
+        }
+
+
         private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
         {
             // Get the subdirectories for the specified directory.
@@ -129,7 +265,7 @@ namespace PackTool
                 Directory.CreateDirectory(productRootFolder);
             }
             var productFolder = Path.Combine(productRootFolder, productName);
-            if(!Directory.Exists(productFolder))
+            if (!Directory.Exists(productFolder))
             {
                 Directory.CreateDirectory(productFolder);
             }
@@ -166,7 +302,7 @@ namespace PackTool
             }
         }
 
-        private static void RepackProduct(string productName, bool attachTimestamp)
+        private static void RepackProduct(string productName, string[] excludeFolderNames, bool attachTimestamp)
         {
             var productRootFolder = Environment.GetEnvironmentVariable("ProductFolder");
             if (string.IsNullOrEmpty(productRootFolder))
@@ -185,8 +321,14 @@ namespace PackTool
                 Directory.CreateDirectory(productFolder);
             }
 
+            var excludeFolders = new List<string>();
+            foreach (var excludeFolderName in excludeFolderNames)
+            {
+                excludeFolders.Add(Path.Combine(productFolder.ToLower(), excludeFolderName.ToLower()));
+            }
+
             var repackRootFolder = Environment.GetEnvironmentVariable("RepackFolder");
-            if(string.IsNullOrEmpty(repackRootFolder))
+            if (string.IsNullOrEmpty(repackRootFolder))
             {
                 Console.WriteLine("The environment variable [RepackFolder] is missing, use default repack folder.");
                 //Using default repackFolder
@@ -196,8 +338,8 @@ namespace PackTool
             {
                 Directory.CreateDirectory(repackRootFolder);
             }
-            var repackFolder = Path.Combine(repackRootFolder, productName);
-            if(!Directory.Exists(repackFolder))
+            var repackFolder = Path.Combine(repackRootFolder, productName, DateTime.Now.ToString("yyyyMMdd"));
+            if (!Directory.Exists(repackFolder))
             {
                 Directory.CreateDirectory(repackFolder);
             }
@@ -219,10 +361,10 @@ namespace PackTool
             {
                 File.Delete(repackFilePath);
             }
-            ZipFile.CreateFromDirectory(productFolder, repackFilePath);
+            CreateZipFileFromDir(productFolder, repackFilePath, excludeFolders.ToArray());
         }
 
-        private static void HandleCopy(Dictionary<string,string> argMap)
+        private static void HandleCopy(Dictionary<string, string> argMap)
         {
             //Copy the file/s
             if (!argMap.TryGetValue("/rs", out var receivedSource))
@@ -256,7 +398,7 @@ namespace PackTool
             CopyFiles(receivedSource, extractDest, repoName, productName, unzip);
         }
 
-        private static void HandleUpdateVersion(Dictionary<string,string> argMap)
+        private static void HandleUpdateVersion(Dictionary<string, string> argMap)
         {
             //Only update version.
             if (!argMap.TryGetValue("/pn", out var productName))
@@ -277,13 +419,19 @@ namespace PackTool
             UpdateVersion(productName, repoName, repoVersion);
         }
 
-        private static void HandleRepack(Dictionary<string,string> argMap)
+        private static void HandleRepack(Dictionary<string, string> argMap)
         {
             if (!argMap.TryGetValue("/pn", out var productName))
             {
                 Console.WriteLine($"The [/pn] - product name argument is missing.");
                 return;
             }
+            var excludFoldereNames = new List<string>();
+            if (argMap.TryGetValue("/ef", out var excludes))
+            {
+                excludFoldereNames.AddRange(excludes.Split(','));
+            }
+            Console.WriteLine($"Exclude folders: [{string.Join(',', excludFoldereNames)}]");
             var attachTimestamp = true;
             if (argMap.TryGetValue("/at", out var attachTimestampStr))
             {
@@ -292,7 +440,7 @@ namespace PackTool
                     Console.WriteLine($"The attachTimestamp argument {attachTimestampStr} is not a bool value.");
                 }
             }
-            RepackProduct(productName, attachTimestamp);
+            RepackProduct(productName, excludFoldereNames.ToArray(), attachTimestamp);
         }
 
 
@@ -324,6 +472,12 @@ namespace PackTool
                 return;
             }
 
+            var excludFoldereNames = new List<string>();
+            if (argMap.TryGetValue("/ef", out var excludes))
+            {
+                excludFoldereNames.AddRange(excludes.Split(','));
+            }
+
             var unzip = false;
             if (argMap.TryGetValue("/unzip", out var unzipStr))
             {
@@ -342,10 +496,10 @@ namespace PackTool
                     Console.WriteLine($"The attachTimestamp argument {attachTimestampStr} is not a bool value.");
                 }
             }
-            RepackProduct(productName, attachTimestamp);
+            RepackProduct(productName, excludFoldereNames.ToArray(), attachTimestamp);
         }
 
-        private static void StartInno(string innoSourceFileName, string setupSource, string productName, string productVersion,string outputDir)
+        private static void StartInno(string innoSourceFileName, string setupSource, string productName, string productVersion, string outputDir)
         {
             var productRootFolder = Environment.GetEnvironmentVariable("ProductFolder");
             if (string.IsNullOrEmpty(productRootFolder))
@@ -367,17 +521,17 @@ namespace PackTool
             var projectSetupSource = Path.Combine(productFolder, setupSource);
             var setupOutputDir = Path.Combine(productFolder, outputDir);
 
-            if(!File.Exists(innoSourceFilePath))
+            if (!File.Exists(innoSourceFilePath))
             {
                 Console.WriteLine("The inno setup source file does not exist.");
                 return;
             }
-            if(!Directory.Exists(projectSetupSource))
+            if (!Directory.Exists(projectSetupSource))
             {
                 Console.WriteLine("The setup project source folder does not exist");
                 return;
             }
-            if(Directory.GetFiles(projectSetupSource).Length == 0)
+            if (Directory.GetFiles(projectSetupSource).Length == 0)
             {
                 Console.WriteLine("No file in setup project source folder.");
                 return;
@@ -441,11 +595,11 @@ namespace PackTool
                 Directory.CreateDirectory(productFolder);
             }
             var target = Path.Combine(productFolder, deleteTraget);
-            if(File.Exists(target))
+            if (File.Exists(target))
             {
                 File.Delete(target);
             }
-            else if(Directory.Exists(target))
+            else if (Directory.Exists(target))
             {
                 Directory.Delete(target, true);
             }
@@ -498,7 +652,7 @@ namespace PackTool
                 mode = "full";
             }
 
-            Console.WriteLine($"Run in {mode} mode.");            
+            Console.WriteLine($"Run in {mode} mode.");
             switch (mode)
             {
                 case "full":

+ 1 - 1
PackTool/Properties/PublishProfiles/FolderProfile.pubxml.user

@@ -4,6 +4,6 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
 -->
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup>
-    <History>True|2021-11-22T01:43:32.4677765Z;True|2021-11-20T13:21:47.0843933+08:00;True|2021-11-20T13:15:32.4634119+08:00;True|2021-11-20T13:14:15.2956703+08:00;True|2021-11-20T11:19:03.4904121+08:00;True|2021-11-20T11:14:52.6831421+08:00;True|2021-11-20T11:07:29.4192692+08:00;True|2021-11-20T10:33:18.9399931+08:00;True|2021-11-20T10:30:40.5235250+08:00;True|2021-11-20T10:30:23.7578090+08:00;True|2021-11-12T10:07:18.1869446+08:00;True|2021-11-12T10:07:00.4300355+08:00;True|2021-11-12T09:15:50.5423048+08:00;True|2021-11-12T09:15:46.7711484+08:00;True|2021-11-12T08:46:22.7243062+08:00;True|2021-11-11T20:37:31.5190040+08:00;True|2021-11-11T20:29:06.2863757+08:00;True|2021-11-11T20:09:35.2068187+08:00;True|2021-11-11T20:07:41.0773244+08:00;True|2021-11-11T20:07:37.8400052+08:00;True|2021-11-11T19:53:34.9129015+08:00;True|2021-11-11T19:47:07.3789470+08:00;True|2021-11-11T19:35:55.0629742+08:00;True|2021-11-11T19:20:10.2529336+08:00;True|2021-11-11T19:08:39.6852088+08:00;</History>
+    <History>True|2021-11-23T07:19:16.1231761Z;True|2021-11-23T15:14:30.1732552+08:00;True|2021-11-23T15:11:40.7930204+08:00;True|2021-11-23T15:10:27.1341187+08:00;True|2021-11-23T15:08:14.3990828+08:00;True|2021-11-23T15:05:08.0026931+08:00;True|2021-11-23T15:03:21.2867589+08:00;True|2021-11-23T14:27:52.7340289+08:00;True|2021-11-23T14:20:54.0543772+08:00;True|2021-11-23T14:17:31.8369735+08:00;True|2021-11-23T14:10:11.2396447+08:00;True|2021-11-23T14:05:39.7775406+08:00;True|2021-11-23T13:56:40.1429785+08:00;True|2021-11-23T09:02:35.3554412+08:00;True|2021-11-23T09:02:15.0537552+08:00;True|2021-11-22T09:43:32.4677765+08:00;True|2021-11-20T13:21:47.0843933+08:00;True|2021-11-20T13:15:32.4634119+08:00;True|2021-11-20T13:14:15.2956703+08:00;True|2021-11-20T11:19:03.4904121+08:00;True|2021-11-20T11:14:52.6831421+08:00;True|2021-11-20T11:07:29.4192692+08:00;True|2021-11-20T10:33:18.9399931+08:00;True|2021-11-20T10:30:40.5235250+08:00;True|2021-11-20T10:30:23.7578090+08:00;True|2021-11-12T10:07:18.1869446+08:00;True|2021-11-12T10:07:00.4300355+08:00;True|2021-11-12T09:15:50.5423048+08:00;True|2021-11-12T09:15:46.7711484+08:00;True|2021-11-12T08:46:22.7243062+08:00;True|2021-11-11T20:37:31.5190040+08:00;True|2021-11-11T20:29:06.2863757+08:00;True|2021-11-11T20:09:35.2068187+08:00;True|2021-11-11T20:07:41.0773244+08:00;True|2021-11-11T20:07:37.8400052+08:00;True|2021-11-11T19:53:34.9129015+08:00;True|2021-11-11T19:47:07.3789470+08:00;True|2021-11-11T19:35:55.0629742+08:00;True|2021-11-11T19:20:10.2529336+08:00;True|2021-11-11T19:08:39.6852088+08:00;</History>
   </PropertyGroup>
 </Project>

+ 3 - 1
PackTool脚本编写说明.docx

@@ -39,6 +39,8 @@ full模式所需参数如下:
 
     /unzip  -  可选参数,如rs参数为一个zip文件,则将此参数设置为true,会将该zip文件直接解压释放到目标文件夹,否则则为直接拷贝该zip文件。默认为false.
 /at -  可选参数,打包输出的zip文件的文件名是否附上时间戳,默认为true。
+/ef -  可选参数,打包输出的zip文件时排除的文件夹。。
+
 
 一个典型的命令行指令如下:
 PackTool /mode=full /pn=flyinsono /rn=Flyinsono /rv=%1 /rs=web\flyinsono.zip /cd=windows_files\App /unzip=true
@@ -84,8 +86,8 @@ repack模式
 
 repack模式所需参数如下:
    /pn -  产品名称,通常客户端为flyinsono,服务端为wing,在打包服务器上会根据产品名产生对应的目录用于释放各仓库的编译输出物。
-
 /at -  可选参数,打包输出的zip文件的文件名是否附上时间戳,默认为true。
+/ef -  可选参数,打包输出的zip文件时排除的文件夹。
 
 以下例子展示了如何打包一个产品目录:
 PackTool /mode=repack /pn=flyinsono