using System; using System.ComponentModel; using System.Diagnostics; using System.Linq; using TeaBox.Macros; using System.IO; namespace TeaBox.Build { [Module] public class CleanUpMacros { [Macro(ThreadAffinity.ExecuteAsync, Icon = "nas")] [DisplayName("Clean Up Data Preflight Directory")] [Category("Robot/NAS")] [Browsable(false)] [Description("Clean up the data preflight directory")] public static void CleanUpDataPreflight( IExecutionContext context, [DefaultValue(1), ParameterDisplayName("Days To Keep"), Description("")] int numberOfDays) { foreach (var folder in Directory.GetDirectories(Studio.Paris.CustomBundleFolder())) { CleanUp(context, folder, 0, numberOfDays); if (!System.IO.Directory.EnumerateFileSystemEntries(folder).Any()) { Directory.Delete(folder); context.LogMessage($"Deleting empty folder {folder}"); } } } [Macro(ThreadAffinity.ExecuteAsync, Icon = "nas")] [DisplayName("Clean Up NAS directory")] [Category("Robot/NAS")] [Description("Clean up a NAS directory.")] public static void CleanUp(IExecutionContext context, string root, [DefaultValue(0), ParameterDisplayName("Folders To Keep"), Description("Minimum number of folders to keep in the root folder")]int folderToKeep, [DefaultValue(5), ParameterDisplayName("Days To Keep"), Description("")] int numberOfDays) { if (!System.IO.Directory.Exists(root)) { context.LogWarning("Directory to clean not found : {0}, cleanup is cancelled", root); return; } var dirInfos = System.IO.Directory.EnumerateDirectories(root) .Select(dirPath => new System.IO.DirectoryInfo(dirPath)) .OrderBy(dirInfo => dirInfo.CreationTime); var count = dirInfos.Count(); // Remove all subdirectories found foreach (var directory in dirInfos) { context.LogMessage($"Count = {count}"); context.LogMessage($"Folder to keep = {folderToKeep}"); // Not necessary to clean since there is less version folders than the minimal number we expect to keep if (count <= folderToKeep) { context.LogMessage("There is only {0} folder(s) remaining at this location, a clean up is not necessary", count); return; } var actualCreationDate = directory.LastWriteTime.Date.Date; context.LogMessage($"Directory Creation Data = {actualCreationDate}"); var days = (DateTime.Today - actualCreationDate).Days; context.LogMessage("Days Between Folder Creation And Today= {days}"); if (days < numberOfDays) { context.LogWarning($"Current folder is not older than {numberOfDays} day(s)"); return; } // Check if the folder should be ignored from the clean up process if (System.IO.File.Exists(Path.Combine(directory.FullName, "clean.ignore"))) { context.LogMessage($"'{directory.FullName}' is older than {numberOfDays} day(s), but will be ignored "); continue; } // Delete folder context.LogMessage($"'{directory.FullName}' is older than {numberOfDays} day(s), it will be cleaned"); if (!Directory.Exists(directory.FullName)) continue; try { Directory.ForceDelete(directory.FullName); count--; } catch (DirectoryNotFoundException) { context.LogWarning("Directory name too long, trying delete using robocopy MIR feature."); DirectoryDeleteLong(directory.FullName); count--; } catch (Exception ex) { context.LogWarning($"Excetion caught {ex.Message} for directory {directory}"); } } } [Macro] [Browsable(false)] public void CleanUpLocalFolder(IExecutionContext context, string folder, bool recursive = false) { if (Directory.Exists(folder)) { Directory.Delete(folder, recursive); context.LogWarning($"{folder} deleted"); } context.LogWarning($"{folder} not found"); } public static void DirectoryDeleteLong(string directoryPath) { var emptyDirectory = new System.IO.DirectoryInfo(Path.GetTempPath() + "\\TempEmptyDirectory-" + Guid.NewGuid()); try { emptyDirectory.Create(); using (var process = new Process()) { process.StartInfo.FileName = "robocopy.exe"; process.StartInfo.Arguments = "\"" + emptyDirectory.FullName + "\" \"" + directoryPath + "\" /mir /r:1 /w:1 /np /xj /sl"; process.StartInfo.UseShellExecute = false; process.StartInfo.CreateNoWindow = true; process.Start(); process.WaitForExit(); } emptyDirectory.Delete(); new System.IO.DirectoryInfo(directoryPath).Attributes = FileAttributes.Normal; Directory.Delete(directoryPath); } catch (IOException) { } } } }