From 12d2779fa3ecb764b697f1835b2b10cc8cb3f97d Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Thu, 29 Jun 2023 22:41:09 -0700 Subject: [PATCH] Save-Image-Info --- .kanbn/index.md | 11 +- .kanbn/tasks/compression-only-difference.md | 14 ++ .vscode/launch.json | 17 +++ Copy-Distinct/CopyDistinct.cs | 10 +- Copy-Distinct/Models/AppSettings.cs | 6 + Copy-Distinct/Models/Binder/AppSettings.cs | 24 +++- Copy-Distinct/appsettings.json | 1 + Instance/DlibDotNet.cs | 3 +- Save-Image-Info/Models/AppSettings.cs | 29 ++++ Save-Image-Info/Models/Binder/AppSettings.cs | 44 ++++++ .../Models/Binder/Configuration.cs | 59 ++++++++ Save-Image-Info/Models/Configuration.cs | 38 ++++++ Save-Image-Info/Models/ImageFileInfo.cs | 21 +++ .../Stateless/SerilogExtensionMethods.cs | 10 ++ Save-Image-Info/Program.cs | 71 ++++++++++ Save-Image-Info/Save-Image-Info.csproj | 60 +++++++++ Save-Image-Info/SaveImageInfo.cs | 121 +++++++++++++++++ Save-Image-Info/appsettings.Development.json | 10 ++ Save-Image-Info/appsettings.json | 126 ++++++++++++++++++ Shared/Models/Stateless/Methods/XPath.cs | 21 ++- View-by-Distance-MKLink-Console.sln | 6 + 21 files changed, 681 insertions(+), 21 deletions(-) create mode 100644 .kanbn/tasks/compression-only-difference.md create mode 100644 Save-Image-Info/Models/AppSettings.cs create mode 100644 Save-Image-Info/Models/Binder/AppSettings.cs create mode 100644 Save-Image-Info/Models/Binder/Configuration.cs create mode 100644 Save-Image-Info/Models/Configuration.cs create mode 100644 Save-Image-Info/Models/ImageFileInfo.cs create mode 100644 Save-Image-Info/Models/Stateless/SerilogExtensionMethods.cs create mode 100644 Save-Image-Info/Program.cs create mode 100644 Save-Image-Info/Save-Image-Info.csproj create mode 100644 Save-Image-Info/SaveImageInfo.cs create mode 100644 Save-Image-Info/appsettings.Development.json create mode 100644 Save-Image-Info/appsettings.json diff --git a/.kanbn/index.md b/.kanbn/index.md index b8bf80b..7ed0220 100644 --- a/.kanbn/index.md +++ b/.kanbn/index.md @@ -11,22 +11,23 @@ completedColumns: - [asdf](tasks/asdf.md) - [merge-scan-photos](tasks/merge-scan-photos.md) +- [setup-syncthing-server](tasks/setup-syncthing-server.md) +- [google-timeline-for-geo](tasks/google-timeline-for-geo.md) +- [use-photo-prism-to-map](tasks/use-photo-prism-to-map.md) +- [import-face-region-metadata](tasks/import-face-region-metadata.md) ## Todo -- [import-face-region-metadata](tasks/import-face-region-metadata.md) -- [use-photo-prism-to-map](tasks/use-photo-prism-to-map.md) - [determine-if-location-container-collection-is-needed-in-get-faces](tasks/determine-if-location-container-collection-is-needed-in-get-faces.md) -- [google-timeline-for-geo](tasks/google-timeline-for-geo.md) - [merge-kristy-files](tasks/merge-kristy-files.md) -- [setup-syncthing-server](tasks/setup-syncthing-server.md) +- [import-know-faces-into-db](tasks/import-know-faces-into-db.md) +- [compression-only-difference](tasks/compression-only-difference.md) ## In Progress - [find-incorrectly-mapped-faces](tasks/find-incorrectly-mapped-faces.md) - [nef-support](tasks/nef-support.md) - [use-eyes-to-find-orientation](tasks/use-eyes-to-find-orientation.md) -- [import-know-faces-into-db](tasks/import-know-faces-into-db.md) ## Done diff --git a/.kanbn/tasks/compression-only-difference.md b/.kanbn/tasks/compression-only-difference.md new file mode 100644 index 0000000..3cbb7bd --- /dev/null +++ b/.kanbn/tasks/compression-only-difference.md @@ -0,0 +1,14 @@ +--- +created: 2023-06-12T21:54:44.803Z +updated: 2023-06-12T21:54:44.803Z +assigned: "" +progress: 0 +tags: [] +status: "1-Backlog" +--- + +# compression-only-difference + +## Sub-tasks + +- [ ] See images -711794998 && -787220963 diff --git a/.vscode/launch.json b/.vscode/launch.json index f60ff10..7fbb2bd 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -259,6 +259,23 @@ "stopAtEntry": false, "requireExactSource": false }, + { + "name": "Save-Image-Info", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/Save-Image-Info/bin/Debug/net7.0/win-x64/Save-Image-Info.dll", + "args": [ + "s" + ], + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "cwd": "${workspaceFolder}", + "console": "externalTerminal", + "stopAtEntry": false, + "requireExactSource": false + }, { "name": "Set-Created-Date", "type": "coreclr", diff --git a/Copy-Distinct/CopyDistinct.cs b/Copy-Distinct/CopyDistinct.cs index 3a61a4c..ce4f513 100644 --- a/Copy-Distinct/CopyDistinct.cs +++ b/Copy-Distinct/CopyDistinct.cs @@ -31,8 +31,7 @@ public class CopyDistinct _ConfigurationRoot = configurationRoot; ILogger? log = Log.ForContext(); Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); - string[] directories = new string[] { propertyConfiguration.ResultContent }; - _FileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(propertyConfiguration, appSettings.CopyTo, directories); + _FileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(propertyConfiguration, appSettings.CopyTo, new string[] { appSettings.ResultDirectoryKey }); Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration); _PropertyConfiguration = propertyConfiguration; _Configuration = configuration; @@ -90,6 +89,7 @@ public class CopyDistinct string directoryName; bool wrapped = false; List distinct = new(); + string key = string.IsNullOrEmpty(_AppSettings.ResultDirectoryKey) ? _PropertyConfiguration.ResultAllInOne : _AppSettings.ResultDirectoryKey; foreach (FileHolder fileHolder in fileHolders) { progressBar.Tick(); @@ -101,17 +101,19 @@ public class CopyDistinct { if (wrapped) continue; - directory = _FileGroups[_PropertyConfiguration.ResultContent][directoryIndex]; + directory = _FileGroups[key][directoryIndex]; } else { if (!wrapped) wrapped = true; - directory = Path.Combine(_FileGroups[_PropertyConfiguration.ResultContent][directoryIndex], directoryName); + directory = Path.Combine(_FileGroups[key][directoryIndex], directoryName); } checkFile = Path.Combine(directory, $"{fileHolder.NameWithoutExtension}{fileHolder.ExtensionLowered}"); if (distinct.Contains(checkFile)) { + if (!_AppSettings.CopyDuplicates) + continue; for (int i = 1; i < int.MaxValue; i++) { fileInfo = new(checkFile); diff --git a/Copy-Distinct/Models/AppSettings.cs b/Copy-Distinct/Models/AppSettings.cs index 5f087eb..aa58310 100644 --- a/Copy-Distinct/Models/AppSettings.cs +++ b/Copy-Distinct/Models/AppSettings.cs @@ -7,19 +7,25 @@ public class AppSettings { public string Company { init; get; } + public bool CopyDuplicates { init; get; } public string CopyTo { init; get; } public int MaxDegreeOfParallelism { init; get; } + public string ResultDirectoryKey { init; get; } public string WorkingDirectoryName { init; get; } [JsonConstructor] public AppSettings(string company, + bool copyDuplicates, string copyTo, int maxDegreeOfParallelism, + string resultDirectoryKey, string workingDirectoryName) { Company = company; CopyTo = copyTo; + CopyDuplicates = copyDuplicates; MaxDegreeOfParallelism = maxDegreeOfParallelism; + ResultDirectoryKey = resultDirectoryKey; WorkingDirectoryName = workingDirectoryName; } diff --git a/Copy-Distinct/Models/Binder/AppSettings.cs b/Copy-Distinct/Models/Binder/AppSettings.cs index 440ae9c..9ea4b19 100644 --- a/Copy-Distinct/Models/Binder/AppSettings.cs +++ b/Copy-Distinct/Models/Binder/AppSettings.cs @@ -6,14 +6,12 @@ namespace View_by_Distance.Copy.Distinct.Models.Binder; public class AppSettings { -#nullable disable - - public string Company { get; set; } + public string? Company { get; set; } public int? MaxDegreeOfParallelism { get; set; } - public string CopyTo { get; set; } - public string WorkingDirectoryName { get; set; } - -#nullable restore + public bool? CopyDuplicates { get; set; } + public string? CopyTo { get; set; } + public string? ResultDirectoryKey { init; get; } + public string? WorkingDirectoryName { get; set; } public override string ToString() { @@ -24,12 +22,24 @@ public class AppSettings private static Models.AppSettings Get(AppSettings? appSettings) { Models.AppSettings result; + if (appSettings?.Company is null) + throw new NullReferenceException(nameof(appSettings.Company)); + if (appSettings?.CopyDuplicates is null) + throw new NullReferenceException(nameof(appSettings.CopyDuplicates)); + if (appSettings?.CopyTo is null) + throw new NullReferenceException(nameof(appSettings.CopyTo)); if (appSettings?.MaxDegreeOfParallelism is null) throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); + if (appSettings?.ResultDirectoryKey is null) + throw new NullReferenceException(nameof(appSettings.ResultDirectoryKey)); + if (appSettings?.WorkingDirectoryName is null) + throw new NullReferenceException(nameof(appSettings.WorkingDirectoryName)); result = new( appSettings.Company, + appSettings.CopyDuplicates.Value, appSettings.CopyTo, appSettings.MaxDegreeOfParallelism.Value, + appSettings.ResultDirectoryKey, appSettings.WorkingDirectoryName ); return result; diff --git a/Copy-Distinct/appsettings.json b/Copy-Distinct/appsettings.json index 9001764..d3768b3 100644 --- a/Copy-Distinct/appsettings.json +++ b/Copy-Distinct/appsettings.json @@ -1,6 +1,7 @@ { "ComparePathsFile": "", "Company": "Mike Phares", + "CopyDuplicates": true, "CopyTo": "", "Linux": {}, "Logging": { diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index c93fc48..4af8e1e 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -794,7 +794,8 @@ public partial class DlibDotNet if (distinctFilteredMappingCollection.Any()) { Shared.Models.Stateless.Methods.IPath.ChangeDateForEmptyDirectories(d2FacePartsContentDirectory, ticks); - Shared.Models.Stateless.Methods.IPath.MakeHiddenIfAllItemsAreHidden(d2FacePartsContentCollectionDirectory); + if (Directory.Exists(d2FacePartsContentCollectionDirectory)) + Shared.Models.Stateless.Methods.IPath.MakeHiddenIfAllItemsAreHidden(d2FacePartsContentCollectionDirectory); } Dictionary> idToWholePercentagesToMapping = Map.Models.Stateless.Methods.IMapLogic.GetIdToWholePercentagesToFace(distinctFilteredMappingCollection); if (Directory.Exists(fPhotoPrismContentDirectory)) diff --git a/Save-Image-Info/Models/AppSettings.cs b/Save-Image-Info/Models/AppSettings.cs new file mode 100644 index 0000000..53e383a --- /dev/null +++ b/Save-Image-Info/Models/AppSettings.cs @@ -0,0 +1,29 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace View_by_Distance.Save.Image.Info.Models; + +public class AppSettings +{ + + public string Company { init; get; } + public int MaxDegreeOfParallelism { init; get; } + public string WorkingDirectoryName { init; get; } + + [JsonConstructor] + public AppSettings(string company, + int maxDegreeOfParallelism, + string workingDirectoryName) + { + Company = company; + MaxDegreeOfParallelism = maxDegreeOfParallelism; + WorkingDirectoryName = workingDirectoryName; + } + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + +} \ No newline at end of file diff --git a/Save-Image-Info/Models/Binder/AppSettings.cs b/Save-Image-Info/Models/Binder/AppSettings.cs new file mode 100644 index 0000000..ba2192b --- /dev/null +++ b/Save-Image-Info/Models/Binder/AppSettings.cs @@ -0,0 +1,44 @@ +using Microsoft.Extensions.Configuration; +using System.Text.Json; + +namespace View_by_Distance.Save.Image.Info.Models.Binder; + +public class AppSettings +{ + + public string? Company { get; set; } + public int? MaxDegreeOfParallelism { get; set; } + public string? WorkingDirectoryName { get; set; } + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + + private static Models.AppSettings Get(AppSettings? appSettings) + { + Models.AppSettings result; + if (appSettings?.Company is null) + throw new NullReferenceException(nameof(appSettings.Company)); + if (appSettings?.MaxDegreeOfParallelism is null) + throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); + if (appSettings?.WorkingDirectoryName is null) + throw new NullReferenceException(nameof(appSettings.WorkingDirectoryName)); + result = new( + appSettings.Company, + appSettings.MaxDegreeOfParallelism.Value, + appSettings.WorkingDirectoryName + ); + return result; + } + + public static Models.AppSettings Get(IConfigurationRoot configurationRoot) + { + Models.AppSettings result; + AppSettings? appSettings = configurationRoot.Get(); + result = Get(appSettings); + return result; + } + +} \ No newline at end of file diff --git a/Save-Image-Info/Models/Binder/Configuration.cs b/Save-Image-Info/Models/Binder/Configuration.cs new file mode 100644 index 0000000..4abfd3f --- /dev/null +++ b/Save-Image-Info/Models/Binder/Configuration.cs @@ -0,0 +1,59 @@ +using Microsoft.Extensions.Configuration; +using Phares.Shared; +using System.ComponentModel.DataAnnotations; +using System.Text.Json; + +namespace View_by_Distance.Save.Image.Info.Models.Binder; + +public class Configuration +{ + +#nullable disable + + [Display(Name = "Ignore Extensions"), Required] public string[] IgnoreExtensions { get; set; } + [Display(Name = "Property Configuration"), Required] public Property.Models.Configuration PropertyConfiguration { get; set; } + [Display(Name = "Person Birthday Format"), Required] public string PersonBirthdayFormat { get; set; } + +#nullable restore + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + + private static Models.Configuration Get(Configuration? configuration) + { + Models.Configuration result; + if (configuration is null) + throw new NullReferenceException(nameof(configuration)); + if (configuration.IgnoreExtensions is null) + throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); + if (configuration.PersonBirthdayFormat is null) + throw new NullReferenceException(nameof(configuration.PersonBirthdayFormat)); + result = new( + configuration.IgnoreExtensions, + configuration.PersonBirthdayFormat, + configuration.PropertyConfiguration); + return result; + } + + public static Models.Configuration Get(IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, Property.Models.Configuration propertyConfiguration) + { + Models.Configuration result; + Configuration? configuration; + if (isEnvironment is null) + configuration = configurationRoot.Get(); + else + { + string environmentName = IsEnvironment.GetEnvironmentName(isEnvironment); + string section = string.Concat(environmentName, ":", nameof(Configuration)); + IConfigurationSection configurationSection = configurationRoot.GetSection(section); + configuration = configurationSection.Get(); + } + result = Get(configuration); + result.SetAndUpdate(propertyConfiguration); + return result; + } + +} \ No newline at end of file diff --git a/Save-Image-Info/Models/Configuration.cs b/Save-Image-Info/Models/Configuration.cs new file mode 100644 index 0000000..f948cbf --- /dev/null +++ b/Save-Image-Info/Models/Configuration.cs @@ -0,0 +1,38 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace View_by_Distance.Save.Image.Info.Models; + +public class Configuration +{ + + protected Property.Models.Configuration _PropertyConfiguration; + public string[] IgnoreExtensions { init; get; } + public string PersonBirthdayFormat { init; get; } + + public Property.Models.Configuration PropertyConfiguration => _PropertyConfiguration; + + [JsonConstructor] + public Configuration( + string[] ignoreExtensions, + string personBirthdayFormat, + Property.Models.Configuration propertyConfiguration) + { + IgnoreExtensions = ignoreExtensions; + PersonBirthdayFormat = personBirthdayFormat; + _PropertyConfiguration = propertyConfiguration; + } + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + + public void SetAndUpdate(Property.Models.Configuration configuration) + { + _PropertyConfiguration = configuration; + _PropertyConfiguration.Update(); + } + +} \ No newline at end of file diff --git a/Save-Image-Info/Models/ImageFileInfo.cs b/Save-Image-Info/Models/ImageFileInfo.cs new file mode 100644 index 0000000..21274d6 --- /dev/null +++ b/Save-Image-Info/Models/ImageFileInfo.cs @@ -0,0 +1,21 @@ +using System.Text.Json.Serialization; + +namespace View_by_Distance.Save.Image.Info.Models; + +public class ImageInfo +{ + + public DateTime? CreationTime { get; init; } + public DateTime? LastWriteTime { get; init; } + public long? Length { get; init; } + public string Name { get; init; } + + [JsonConstructor] + public ImageInfo(DateTime? creationTime, DateTime? lastWriteTime, long? length, string name) + { + CreationTime = creationTime; + LastWriteTime = lastWriteTime; + Length = length; + Name = name; + } +} \ No newline at end of file diff --git a/Save-Image-Info/Models/Stateless/SerilogExtensionMethods.cs b/Save-Image-Info/Models/Stateless/SerilogExtensionMethods.cs new file mode 100644 index 0000000..9985a06 --- /dev/null +++ b/Save-Image-Info/Models/Stateless/SerilogExtensionMethods.cs @@ -0,0 +1,10 @@ +namespace View_by_Distance.Save.Image.Info.Models.Stateless; + +public static class SerilogExtensionMethods +{ + + internal static void Warn(this Serilog.ILogger log, string messageTemplate) => log.Warning(messageTemplate); + + internal static void Info(this Serilog.ILogger log, string messageTemplate) => log.Information(messageTemplate); + +} \ No newline at end of file diff --git a/Save-Image-Info/Program.cs b/Save-Image-Info/Program.cs new file mode 100644 index 0000000..6129298 --- /dev/null +++ b/Save-Image-Info/Program.cs @@ -0,0 +1,71 @@ +using Microsoft.Extensions.Configuration; +using Phares.Shared; +using Serilog; +using System.Diagnostics; +using System.Reflection; +using View_by_Distance.Save.Image.Info.Models; +using View_by_Distance.Shared.Models.Stateless.Methods; + +namespace View_by_Distance.Save.Image.Info; + +public class Program +{ + + public static void Secondary(List args) + { + LoggerConfiguration loggerConfiguration = new(); + Assembly assembly = Assembly.GetExecutingAssembly(); + bool debuggerWasAttachedAtLineZero = Debugger.IsAttached || assembly.Location.Contains(@"\bin\Debug"); + IsEnvironment isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero); + IConfigurationBuilder configurationBuilder = new ConfigurationBuilder() + .AddEnvironmentVariables() + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true) + .AddUserSecrets(); + IConfigurationRoot configurationRoot = configurationBuilder.Build(); + AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot); + if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount) + throw new Exception("MaxDegreeOfParallelism must be =< Environment.ProcessorCount!"); + if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) + throw new Exception("Working directory name must have a value!"); + string workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); + Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); + _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); + Log.Logger = loggerConfiguration.CreateLogger(); + ILogger log = Log.ForContext(); + int silentIndex = args.IndexOf("s"); + if (silentIndex > -1) + args.RemoveAt(silentIndex); + try + { + if (args is null) + throw new Exception("args is null!"); + Shared.Models.Console console = new(); + _ = new SaveImageInfo(args, isEnvironment, configurationRoot, appSettings, workingDirectory, silentIndex > -1, console); + } + catch (Exception ex) + { + log.Fatal(string.Concat(ex.Message, Environment.NewLine, ex.StackTrace)); + } + finally + { + Log.CloseAndFlush(); + } + if (silentIndex > -1) + log.Debug("Done. Bye"); + else + { + log.Debug("Done. Press 'Enter' to end"); + _ = Console.ReadLine(); + } + } + + public static void Main(string[] args) + { + if (args is not null) + Secondary(args.ToList()); + else + Secondary(new List()); + } + +} \ No newline at end of file diff --git a/Save-Image-Info/Save-Image-Info.csproj b/Save-Image-Info/Save-Image-Info.csproj new file mode 100644 index 0000000..d955727 --- /dev/null +++ b/Save-Image-Info/Save-Image-Info.csproj @@ -0,0 +1,60 @@ + + + enable + 10.0 + enable + Exe + win-x64 + net7.0 + fa06c6db-0226-42ca-8728-68b1e336184d + + + Phares.View.by.Distance.Save.Image.Info + false + 7.0.101.1 + Mike Phares + Phares + true + snupkg + + + true + true + true + + + Windows + + + OSX + + + Linux + + + + + + + + + + + + + + + + + + + + + + Always + + + Always + + + \ No newline at end of file diff --git a/Save-Image-Info/SaveImageInfo.cs b/Save-Image-Info/SaveImageInfo.cs new file mode 100644 index 0000000..4bac9c5 --- /dev/null +++ b/Save-Image-Info/SaveImageInfo.cs @@ -0,0 +1,121 @@ +using Microsoft.Extensions.Configuration; +using Phares.Shared; +using Serilog; +using ShellProgressBar; +using System.Text; +using System.Text.Json; +using View_by_Distance.Save.Image.Info.Models; +using View_by_Distance.Shared.Models; +using View_by_Distance.Shared.Models.Methods; + +namespace View_by_Distance.Save.Image.Info; + +public class SaveImageInfo +{ + + private readonly AppSettings _AppSettings; + private readonly string _WorkingDirectory; + private readonly Configuration _Configuration; + private readonly IsEnvironment _IsEnvironment; + private readonly IConfigurationRoot _ConfigurationRoot; + private readonly Property.Models.Configuration _PropertyConfiguration; + + public SaveImageInfo(List args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) + { + if (isSilent) + { } + if (console is null) + { } + _AppSettings = appSettings; + _IsEnvironment = isEnvironment; + _WorkingDirectory = workingDirectory; + _ConfigurationRoot = configurationRoot; + ILogger? log = Log.ForContext(); + Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); + Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration); + _PropertyConfiguration = propertyConfiguration; + _Configuration = configuration; + propertyConfiguration.Update(); + log.Information(propertyConfiguration.RootDirectory); + Verify(); + List lines = SaveImageInfoFilesInDirectories(log); + File.WriteAllLines($"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv", lines); + if (!lines.Any()) + _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); + } + + private void Verify() + { + if (_AppSettings is null) + { } + if (_IsEnvironment is null) + { } + if (_Configuration is null) + { } + if (_ConfigurationRoot is null) + { } + if (_WorkingDirectory is null) + { } + if (_PropertyConfiguration is null) + { } + } + + private static StringBuilder GetLines(ProgressBar progressBar, List filesCollection) + { + StringBuilder result = new(); + string json; + string? directory; + ImageInfo imageInfo; + FileHolder[] fileHolders; + List lines = new(); + foreach (string[] files in filesCollection) + { + lines.Clear(); + progressBar.Tick(); + fileHolders = (from l in files select new FileHolder(l)).ToArray(); + foreach (FileHolder fileHolder in from l in fileHolders orderby l.Name.Length, l.Name select l) + { + if (fileHolder.ExtensionLowered == ".id" || fileHolder.ExtensionLowered == ".lsv" || fileHolder.DirectoryName is null) + continue; + imageInfo = new(fileHolder.CreationTime, fileHolder.LastWriteTime, fileHolder.Length, fileHolder.Name); + json = JsonSerializer.Serialize(imageInfo); + lines.Add(json); + } + if (lines.Any()) + { + directory = Path.GetDirectoryName(files.First()); + if (directory is null) + continue; + _ = result.AppendLine(directory); + foreach (string line in lines) + _ = result.AppendLine(line); + } + } + return result; + } + + private void Save(StringBuilder stringBuilder) + { + string checkFile = Path.Combine(_PropertyConfiguration.RootDirectory, ".json"); + string text = stringBuilder.ToString(); + _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, text, updateToWhenMatches: null, compareBeforeWrite: true, updateDateWhenMatches: false); + } + + private List SaveImageInfoFilesInDirectories(ILogger log) + { + List results = new(); + ProgressBar progressBar; + const string fileSearchFilter = "*"; + string message = nameof(SaveImageInfo); + const string directorySearchFilter = "*"; + List distinctDirectories = new(); + List filesCollection = Shared.Models.Stateless.Methods.IDirectory.GetFilesCollection(_PropertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter); + ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; + progressBar = new(filesCollection.Count, message, options); + StringBuilder lines = GetLines(progressBar, filesCollection); + progressBar.Dispose(); + Save(lines); + return results; + } + +} \ No newline at end of file diff --git a/Save-Image-Info/appsettings.Development.json b/Save-Image-Info/appsettings.Development.json new file mode 100644 index 0000000..ad9619a --- /dev/null +++ b/Save-Image-Info/appsettings.Development.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Log4netProvider": "Debug" + } + }, + "Serilog": { + "MinimumLevel": "Debug" + } +} \ No newline at end of file diff --git a/Save-Image-Info/appsettings.json b/Save-Image-Info/appsettings.json new file mode 100644 index 0000000..ed0997e --- /dev/null +++ b/Save-Image-Info/appsettings.json @@ -0,0 +1,126 @@ +{ + "Company": "Mike Phares", + "Linux": {}, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Log4netProvider": "Debug", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "MaxDegreeOfParallelism": 6, + "Serilog": { + "Using": [ + "Serilog.Sinks.Console", + "Serilog.Sinks.File" + ], + "MinimumLevel": "Information", + "WriteTo": [ + { + "Name": "Debug", + "Args": { + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}" + } + }, + { + "Name": "Console", + "Args": { + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "%workingDirectory% - Log/log-.txt", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}", + "rollingInterval": "Hour" + } + } + ], + "Enrich": [ + "FromLogContext", + "WithMachineName", + "WithThreadId" + ], + "Properties": { + "Application": "Sample" + } + }, + "WorkingDirectoryName": "PharesApps", + "Windows": { + "Configuration": { + "DateGroup": "dd514b88", + "DiffPropertyDirectory": "", + "FileNameDirectorySeparator": ".Z.", + "ForcePropertyLastWriteTimeToCreationTime": false, + "MaxImagesInDirectoryForTopLevelFirstPass": 10, + "OutputExtension": ".jpg", + "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", + "PersonBirthdayFormat": "yyyy-MM-dd_HH", + "PopulatePropertyId": true, + "PropertiesChangedForProperty": false, + "ResultAllInOne": "_ _ _", + "ResultAllInOneSubdirectoryLength": 2, + "ResultCollection": "[]", + "ResultContent": "()", + "ResultSingleton": "{}", + "RootDirectory": "D:/Images", + "WriteBitmapDataBytes": false, + "IgnoreExtensions": [ + ".gif", + ".GIF", + ".nef", + ".NEF", + ".pdf", + ".PDF" + ], + "ValidImageFormatExtensions": [ + ".bmp", + ".BMP", + ".gif", + ".GIF", + ".jpeg", + ".JPEG", + ".jpg", + ".JPG", + ".png", + ".PNG", + ".tiff", + ".TIFF", + ".tif", + ".TIF" + ], + "ValidMetadataExtensions": [ + ".3gp", + ".3GP", + ".avi", + ".AVI", + ".bmp", + ".BMP", + ".gif", + ".GIF", + ".ico", + ".ICO", + ".jpeg", + ".JPEG", + ".jpg", + ".JPG", + ".m4v", + ".M4V", + ".mov", + ".MOV", + ".mp4", + ".MP4", + ".mta", + ".MTA", + ".png", + ".PNG", + ".tiff", + ".TIFF", + ".tif", + ".TIF" + ] + } + } +} \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/XPath.cs b/Shared/Models/Stateless/Methods/XPath.cs index e96216f..72e94de 100644 --- a/Shared/Models/Stateless/Methods/XPath.cs +++ b/Shared/Models/Stateless/Methods/XPath.cs @@ -293,15 +293,28 @@ internal abstract class XPath collection.Clear(); for (int i = 0; i < plusOne; i++) { - if (i == converted) - checkDirectory = Path.GetFullPath(Path.Combine(resultsFullGroupDirectory, key, propertyConfiguration.ResultAllInOne, new('-', propertyConfiguration.ResultAllInOneSubdirectoryLength))); + if (string.IsNullOrEmpty(key)) + { + if (i == converted) + checkDirectory = Path.GetFullPath(Path.Combine(resultsFullGroupDirectory, new('-', propertyConfiguration.ResultAllInOneSubdirectoryLength))); + else + checkDirectory = Path.GetFullPath(Path.Combine(resultsFullGroupDirectory, i.ToString().PadLeft(propertyConfiguration.ResultAllInOneSubdirectoryLength, '0'))); + } else - checkDirectory = Path.GetFullPath(Path.Combine(resultsFullGroupDirectory, key, propertyConfiguration.ResultAllInOne, i.ToString().PadLeft(propertyConfiguration.ResultAllInOneSubdirectoryLength, '0'))); + { + if (i == converted) + checkDirectory = Path.GetFullPath(Path.Combine(resultsFullGroupDirectory, key, propertyConfiguration.ResultAllInOne, new('-', propertyConfiguration.ResultAllInOneSubdirectoryLength))); + else + checkDirectory = Path.GetFullPath(Path.Combine(resultsFullGroupDirectory, key, propertyConfiguration.ResultAllInOne, i.ToString().PadLeft(propertyConfiguration.ResultAllInOneSubdirectoryLength, '0'))); + } if (!Directory.Exists(checkDirectory)) _ = Directory.CreateDirectory(checkDirectory); collection.Add(checkDirectory); } - results.Add(key, collection.ToArray()); + if (!string.IsNullOrEmpty(key)) + results.Add(key, collection.ToArray()); + else + results.Add(propertyConfiguration.ResultAllInOne, collection.ToArray()); } } return results; diff --git a/View-by-Distance-MKLink-Console.sln b/View-by-Distance-MKLink-Console.sln index f5ee58b..ee36911 100644 --- a/View-by-Distance-MKLink-Console.sln +++ b/View-by-Distance-MKLink-Console.sln @@ -51,6 +51,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rename", "Rename\Rename.csp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Resize", "Resize\Resize.csproj", "{27D0D869-394D-4B07-83DF-2095B16026FC}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Save-Image-Info", "Save-Image-Info\Save-Image-Info.csproj", "{22B8C2B6-2D6E-4166-86CD-D37D11617A79}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Set-Created-Date", "Set-Created-Date\Set-Created-Date.csproj", "{B067643E-9F59-46A1-A001-ACF4661F059C}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{B4FB6B43-36EC-404D-B934-5C695C6E32CC}" @@ -190,5 +192,9 @@ Global {B067643E-9F59-46A1-A001-ACF4661F059C}.Debug|Any CPU.Build.0 = Debug|Any CPU {B067643E-9F59-46A1-A001-ACF4661F059C}.Release|Any CPU.ActiveCfg = Release|Any CPU {B067643E-9F59-46A1-A001-ACF4661F059C}.Release|Any CPU.Build.0 = Release|Any CPU + {22B8C2B6-2D6E-4166-86CD-D37D11617A79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {22B8C2B6-2D6E-4166-86CD-D37D11617A79}.Debug|Any CPU.Build.0 = Debug|Any CPU + {22B8C2B6-2D6E-4166-86CD-D37D11617A79}.Release|Any CPU.ActiveCfg = Release|Any CPU + {22B8C2B6-2D6E-4166-86CD-D37D11617A79}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal