390 lines
18 KiB
C#
390 lines
18 KiB
C#
using Microsoft.Extensions.Logging;
|
|
using System.Globalization;
|
|
using System.IO.Compression;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace File_Folder_Helper.Helpers;
|
|
|
|
internal static partial class HelperZipFilesBy
|
|
{
|
|
|
|
private static DateTimeOffset? GetDateTimeOffset(string keyFileExtension, FileInfo fileInfo, FileInfo extractKeyFileInfo)
|
|
{
|
|
DateTimeOffset? dateTimeOffset = null;
|
|
using ZipArchive zip = ZipFile.Open(fileInfo.FullName, ZipArchiveMode.Read);
|
|
foreach (ZipArchiveEntry zipArchiveEntry in zip.Entries)
|
|
{
|
|
if (!zipArchiveEntry.Name.EndsWith(keyFileExtension))
|
|
continue;
|
|
dateTimeOffset = zipArchiveEntry.LastWriteTime;
|
|
if (fileInfo.FullName[0] != '\\')
|
|
{
|
|
zipArchiveEntry.ExtractToFile(extractKeyFileInfo.FullName);
|
|
File.SetCreationTime(extractKeyFileInfo.FullName, fileInfo.CreationTime);
|
|
File.SetLastWriteTime(extractKeyFileInfo.FullName, dateTimeOffset.Value.LocalDateTime);
|
|
}
|
|
break;
|
|
}
|
|
return dateTimeOffset;
|
|
}
|
|
|
|
[GeneratedRegex("[a-zA-Z0-9]{1,}")]
|
|
private static partial Regex LowerAlphaAlphaAndNumber();
|
|
|
|
private static bool ExtractKeyFileAndSetDateFromZipEntry(ILogger<Worker> logger, string[] zipFiles, string keyFileExtension, string keyFileExtensionB, string keyFileExtensionC, bool renameToLower)
|
|
{
|
|
bool result = false;
|
|
string[] files;
|
|
string checkFile;
|
|
string? lowerName;
|
|
FileInfo fileInfo;
|
|
FileInfo extractKeyFileInfo;
|
|
DateTimeOffset? dateTimeOffset;
|
|
foreach (string zipFile in zipFiles)
|
|
{
|
|
fileInfo = new(zipFile);
|
|
if (fileInfo.DirectoryName is null)
|
|
throw new NullReferenceException(nameof(fileInfo.DirectoryName));
|
|
lowerName = !renameToLower ? null : Path.Combine(fileInfo.DirectoryName, fileInfo.Name.ToLower());
|
|
if (renameToLower && lowerName is not null && lowerName != fileInfo.FullName)
|
|
{
|
|
files = Directory.GetFiles(fileInfo.DirectoryName, $"{Path.GetFileNameWithoutExtension(fileInfo.Name)}*", SearchOption.TopDirectoryOnly);
|
|
foreach (string file in files)
|
|
File.Move(file, Path.Combine(fileInfo.DirectoryName, Path.GetFileName(file).ToLower()));
|
|
fileInfo = new(lowerName);
|
|
if (fileInfo.DirectoryName is null)
|
|
throw new NullReferenceException(nameof(fileInfo.DirectoryName));
|
|
}
|
|
extractKeyFileInfo = new(Path.Combine(fileInfo.DirectoryName, $"{Path.GetFileNameWithoutExtension(fileInfo.Name)}{keyFileExtension}"));
|
|
if (extractKeyFileInfo.Exists)
|
|
{
|
|
if (extractKeyFileInfo.CreationTime.ToString("yyyy-MM-dd") == fileInfo.CreationTime.ToString("yyyy-MM-dd") && extractKeyFileInfo.LastWriteTime.ToString("yyyy-MM-dd") == fileInfo.LastWriteTime.ToString("yyyy-MM-dd"))
|
|
continue;
|
|
File.Delete(extractKeyFileInfo.FullName);
|
|
}
|
|
try
|
|
{
|
|
dateTimeOffset = GetDateTimeOffset(keyFileExtension, fileInfo, extractKeyFileInfo);
|
|
if (dateTimeOffset is null)
|
|
continue;
|
|
if (fileInfo.LastWriteTime != dateTimeOffset.Value.LocalDateTime)
|
|
{
|
|
File.SetLastWriteTime(fileInfo.FullName, dateTimeOffset.Value.LocalDateTime);
|
|
if (!result)
|
|
result = true;
|
|
}
|
|
if (string.IsNullOrEmpty(keyFileExtensionB))
|
|
continue;
|
|
files = Directory.GetFiles(fileInfo.DirectoryName, keyFileExtensionB, SearchOption.TopDirectoryOnly);
|
|
foreach (string file in files)
|
|
{
|
|
fileInfo = new(file);
|
|
if (fileInfo.LastWriteTime != dateTimeOffset.Value.LocalDateTime)
|
|
{
|
|
File.SetLastWriteTime(fileInfo.FullName, dateTimeOffset.Value.LocalDateTime);
|
|
if (!result)
|
|
result = true;
|
|
}
|
|
}
|
|
if (string.IsNullOrEmpty(keyFileExtensionC))
|
|
continue;
|
|
if (fileInfo.DirectoryName is null)
|
|
throw new NullReferenceException(nameof(fileInfo.DirectoryName));
|
|
files = Directory.GetFiles(fileInfo.DirectoryName, keyFileExtensionC, SearchOption.TopDirectoryOnly);
|
|
foreach (string file in files)
|
|
{
|
|
fileInfo = new(file);
|
|
if (fileInfo.LastWriteTime != dateTimeOffset.Value.LocalDateTime)
|
|
{
|
|
File.SetLastWriteTime(fileInfo.FullName, dateTimeOffset.Value.LocalDateTime);
|
|
if (!result)
|
|
result = true;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
logger.LogInformation("<{zipFile}> is invalid!", zipFile);
|
|
checkFile = string.Concat(zipFile, ".err");
|
|
for (int e = 0; e < short.MaxValue; e++)
|
|
{
|
|
if (!File.Exists(checkFile))
|
|
break;
|
|
checkFile = string.Concat(checkFile, e);
|
|
}
|
|
try
|
|
{ File.Move(zipFile, checkFile); }
|
|
catch (Exception) { logger.LogInformation("<{zipFile}> couldn't be moved!", zipFile); }
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private static void ZipDirectory(ILogger<Worker> logger, string directory)
|
|
{
|
|
logger.LogInformation("{directory}", directory);
|
|
string zipFile = $"{directory}.zip";
|
|
int skipChars = directory.Length + 1;
|
|
string[] files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories);
|
|
string[] directories = Directory.GetDirectories(directory, "*", SearchOption.AllDirectories);
|
|
ZipArchiveMode zipArchiveMode = File.Exists(zipFile) ? ZipArchiveMode.Update : ZipArchiveMode.Create;
|
|
for (int i = 1; i < 3; i++)
|
|
{
|
|
try
|
|
{
|
|
using ZipArchive zip = ZipFile.Open(zipFile, zipArchiveMode);
|
|
for (int j = 0; j < directories.Length; j++)
|
|
_ = zip.CreateEntry($"{directories[j][skipChars..]}/");
|
|
foreach (string file in files)
|
|
{
|
|
_ = zip.CreateEntryFromFile(file, file[skipChars..]);
|
|
File.Delete(file);
|
|
}
|
|
break;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
File.Delete(zipFile);
|
|
zipArchiveMode = ZipArchiveMode.Create;
|
|
}
|
|
}
|
|
Directory.Delete(directory, recursive: true);
|
|
}
|
|
|
|
internal static bool ZipFilesByDate(ILogger<Worker> logger, string sourceDirectory, SearchOption searchOption = SearchOption.TopDirectoryOnly, string dayFormat = "")
|
|
{
|
|
bool result = false;
|
|
string key;
|
|
bool addFile;
|
|
string fileName;
|
|
string? zipPath;
|
|
FileInfo fileInfo;
|
|
string weekOfYear;
|
|
string[] segments;
|
|
string[] subFiles;
|
|
string zipDirectory;
|
|
DateTime creationTime;
|
|
string? directoryName;
|
|
DateTime lastWriteTime;
|
|
DateTime nowDateTime = DateTime.Now;
|
|
DateTime dateTime = DateTime.MinValue;
|
|
DateTime firstEmail = new(2019, 3, 8);
|
|
CultureInfo cultureInfo = new("en-US");
|
|
Dictionary<string, DateTime> weeks = [];
|
|
Calendar calendar = cultureInfo.Calendar;
|
|
Regex regex = LowerAlphaAlphaAndNumber();
|
|
int ticksLength = nowDateTime.AddDays(-6).Ticks.ToString().Length;
|
|
for (int i = 0; i < int.MaxValue; i++)
|
|
{
|
|
dateTime = firstEmail.AddDays(i);
|
|
if (dateTime > nowDateTime)
|
|
break;
|
|
weekOfYear = calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
|
|
key = string.Concat(dateTime.ToString("yyyy"), "_Week_", weekOfYear);
|
|
if (!weeks.ContainsKey(key))
|
|
weeks.Add(key, dateTime);
|
|
}
|
|
weekOfYear = calendar.GetWeekOfYear(nowDateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
|
|
string skipKey = string.Concat(nowDateTime.ToString("yyyy"), "_Week_", weekOfYear);
|
|
Dictionary<string, List<string>> keyValuePairs = [];
|
|
string[] topDirectories = Directory.GetDirectories(sourceDirectory, "*", SearchOption.TopDirectoryOnly);
|
|
if (topDirectories.Length == 0)
|
|
topDirectories = [sourceDirectory];
|
|
foreach (string topDirectory in topDirectories)
|
|
{
|
|
keyValuePairs.Clear();
|
|
directoryName = Path.GetDirectoryName(topDirectory);
|
|
subFiles = Directory.GetFiles(topDirectory, "*", searchOption);
|
|
zipPath = string.IsNullOrEmpty(directoryName) ? null : Path.Combine(directoryName, "ZipPath");
|
|
zipDirectory = zipPath is not null && Directory.Exists(zipPath) ? zipPath : topDirectory;
|
|
foreach (string subFile in subFiles)
|
|
{
|
|
addFile = false;
|
|
if (subFile.EndsWith(".zip"))
|
|
continue;
|
|
fileName = Path.GetFileName(subFile);
|
|
fileInfo = new FileInfo(subFile);
|
|
creationTime = fileInfo.CreationTime;
|
|
if (creationTime > dateTime)
|
|
continue;
|
|
lastWriteTime = fileInfo.LastWriteTime;
|
|
if (fileName.Contains(lastWriteTime.ToString("yyyyMMdd")) || fileName.Contains(lastWriteTime.ToString("yyyy-MM-dd")) ||
|
|
fileName.Contains(creationTime.ToString("yyyyMMdd")) || fileName.Contains(creationTime.ToString("yyyy-MM-dd")) ||
|
|
fileName.Contains(lastWriteTime.ToString("yyMMdd")) || fileName.Contains(lastWriteTime.ToString("yy-MM-dd")) ||
|
|
fileName.Contains(creationTime.ToString("yyMMdd")) || fileName.Contains(creationTime.ToString("yy-MM-dd")) ||
|
|
fileName.Contains(lastWriteTime.AddDays(-1).ToString("yyyyMMdd")) || fileName.Contains(lastWriteTime.AddDays(-1).ToString("yyyy-MM-dd")) ||
|
|
fileName.Contains(creationTime.AddDays(-1).ToString("yyyyMMdd")) || fileName.Contains(creationTime.AddDays(-1).ToString("yyyy-MM-dd")) ||
|
|
fileName.Contains(lastWriteTime.AddDays(-1).ToString("yyMMdd")) || fileName.Contains(lastWriteTime.AddDays(-1).ToString("yy-MM-dd")) ||
|
|
fileName.Contains(creationTime.AddDays(-1).ToString("yyMMdd")) || fileName.Contains(creationTime.AddDays(-1).ToString("yy-MM-dd")))
|
|
addFile = true;
|
|
if (!addFile && fileName.Length > ticksLength)
|
|
{
|
|
MatchCollection matches = regex.Matches(fileName);
|
|
foreach (Match match in matches.Cast<Match>())
|
|
{
|
|
if (match.Value.Length != ticksLength)
|
|
continue;
|
|
if (!long.TryParse(match.Value, out long ticks))
|
|
continue;
|
|
addFile = true;
|
|
break;
|
|
}
|
|
if (addFile)
|
|
break;
|
|
}
|
|
if (addFile)
|
|
{
|
|
weekOfYear = calendar.GetWeekOfYear(lastWriteTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
|
|
if (string.IsNullOrEmpty(dayFormat))
|
|
key = string.Concat(lastWriteTime.ToString("yyyy"), "_Week_", weekOfYear);
|
|
else
|
|
key = string.Concat(lastWriteTime.ToString("yyyy"), "_Week_", weekOfYear, "_", lastWriteTime.ToString(dayFormat));
|
|
if (key == skipKey)
|
|
continue;
|
|
if (!keyValuePairs.ContainsKey(key))
|
|
keyValuePairs.Add(key, []);
|
|
keyValuePairs[key].Add(subFile);
|
|
}
|
|
}
|
|
foreach (KeyValuePair<string, List<string>> element in keyValuePairs)
|
|
{
|
|
key = Path.Combine(zipDirectory, $"{element.Key}.zip");
|
|
if (File.Exists(key))
|
|
for (short i = 101; i < short.MaxValue; i++)
|
|
{
|
|
key = Path.Combine(zipDirectory, $"{element.Key}_{i}.zip");
|
|
if (!File.Exists(key))
|
|
break;
|
|
}
|
|
using ZipArchive zip = ZipFile.Open(key, ZipArchiveMode.Create);
|
|
foreach (string file in element.Value)
|
|
{
|
|
_ = zip.CreateEntryFromFile(file, Path.GetFileName(file));
|
|
File.Delete(file);
|
|
}
|
|
if (zipPath is not null && Directory.Exists(zipPath) && !string.IsNullOrEmpty(directoryName))
|
|
try
|
|
{ Directory.SetLastWriteTime(directoryName, DateTime.Now); }
|
|
catch (Exception) { }
|
|
}
|
|
subFiles = Directory.GetFiles(zipDirectory, "*.zip", SearchOption.TopDirectoryOnly);
|
|
foreach (string subFile in subFiles)
|
|
{
|
|
fileName = Path.GetFileNameWithoutExtension(subFile);
|
|
segments = fileName.Split('_');
|
|
if (segments.Length > 2)
|
|
fileName = string.Concat(segments[0], '_', segments[1], '_', segments[2]);
|
|
if (weeks.TryGetValue(fileName, out DateTime value))
|
|
try
|
|
{
|
|
if (!result)
|
|
result = true;
|
|
File.SetLastWriteTime(subFile, value);
|
|
}
|
|
catch (Exception) { }
|
|
}
|
|
if (topDirectory != sourceDirectory)
|
|
try
|
|
{ HelperDeleteEmptyDirectories.DeleteEmptyDirectories(logger, topDirectory); }
|
|
catch (Exception) { }
|
|
logger.LogInformation("{topDirectory}", topDirectory);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
internal static bool ExportNuspecAndSetDateFromZipEntry(ILogger<Worker> logger, string[] files, bool renameToLower) =>
|
|
ExtractKeyFileAndSetDateFromZipEntry(logger, files, ".nuspec", "icon", "readme", renameToLower);
|
|
|
|
internal static bool ExtractKeyFileAndSetDateFromZipEntry(ILogger<Worker> logger, string sourceDirectory, SearchOption searchOption = SearchOption.AllDirectories, bool renameToLower = false)
|
|
{
|
|
bool result = false;
|
|
bool loop;
|
|
string[] zipFiles;
|
|
string searchPattern;
|
|
string keyFileExtension;
|
|
string keyFileExtensionB;
|
|
string keyFileExtensionC;
|
|
if (!Directory.Exists(sourceDirectory))
|
|
_ = Directory.CreateDirectory(sourceDirectory);
|
|
for (int i = 1; i < 3; i++)
|
|
{
|
|
(searchPattern, keyFileExtension, keyFileExtensionB, keyFileExtensionC) = i switch
|
|
{
|
|
1 => ("*.nupkg", ".nuspec", "icon", "readme"),
|
|
2 => ("*.vsix", ".vsixmanifest", string.Empty, string.Empty),
|
|
_ => throw new NotSupportedException()
|
|
};
|
|
zipFiles = Directory.GetFiles(sourceDirectory, searchPattern, searchOption);
|
|
loop = ExtractKeyFileAndSetDateFromZipEntry(logger, zipFiles, keyFileExtension, keyFileExtensionB, keyFileExtensionC, renameToLower);
|
|
if (loop && !result)
|
|
result = true;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
internal static void ZipFilesByDirectoryWithFile(ILogger<Worker> logger, string sourceDirectory)
|
|
{
|
|
string[] files1;
|
|
string[] files2;
|
|
string[] files3;
|
|
string[] files4;
|
|
string[] files5;
|
|
string[] directories2;
|
|
string[] directories3;
|
|
string[] directories4;
|
|
string[] directories5;
|
|
string[] directories1 = Directory.GetDirectories(sourceDirectory, "*", SearchOption.TopDirectoryOnly);
|
|
foreach (string directory1 in directories1)
|
|
{
|
|
files1 = Directory.GetFiles(directory1, "*", SearchOption.TopDirectoryOnly).Where(l => !l.EndsWith(".zip")).ToArray();
|
|
if (files1.Length > 0)
|
|
{
|
|
ZipDirectory(logger, directory1);
|
|
continue;
|
|
}
|
|
directories2 = Directory.GetDirectories(directory1, "*", SearchOption.TopDirectoryOnly);
|
|
foreach (string directory2 in directories2)
|
|
{
|
|
files2 = Directory.GetFiles(directory2, "*", SearchOption.TopDirectoryOnly).Where(l => !l.EndsWith(".zip")).ToArray();
|
|
if (files2.Length > 0)
|
|
{
|
|
ZipDirectory(logger, directory2);
|
|
continue;
|
|
}
|
|
directories3 = Directory.GetDirectories(directory2, "*", SearchOption.TopDirectoryOnly);
|
|
foreach (string directory3 in directories3)
|
|
{
|
|
files3 = Directory.GetFiles(directory3, "*", SearchOption.TopDirectoryOnly).Where(l => !l.EndsWith(".zip")).ToArray();
|
|
if (files3.Length > 0)
|
|
{
|
|
ZipDirectory(logger, directory3);
|
|
continue;
|
|
}
|
|
directories4 = Directory.GetDirectories(directory3, "*", SearchOption.TopDirectoryOnly);
|
|
foreach (string directory4 in directories4)
|
|
{
|
|
files4 = Directory.GetFiles(directory4, "*", SearchOption.TopDirectoryOnly).Where(l => !l.EndsWith(".zip")).ToArray();
|
|
if (files4.Length > 0)
|
|
{
|
|
ZipDirectory(logger, directory4);
|
|
continue;
|
|
}
|
|
directories5 = Directory.GetDirectories(directory4, "*", SearchOption.TopDirectoryOnly);
|
|
foreach (string directory5 in directories5)
|
|
{
|
|
files5 = Directory.GetFiles(directory5, "*", SearchOption.TopDirectoryOnly);
|
|
if (files5.Length == 0)
|
|
throw new NotSupportedException("Files are too deep!");
|
|
else
|
|
{
|
|
ZipDirectory(logger, directory5);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} |