Compare commits

...

10 Commits

Author SHA1 Message Date
f6e6fa712f Bump 2024-08-17 10:58:54 -07:00
a878fe3253 Bump 2024-07-19 12:00:44 -07:00
2a305c69f0 #pragma warning disable IDE0060 2024-06-24 17:20:45 -07:00
8a817750c9 Prep for item.FilePath.HasIgnoreKeyword, item.FilePath.HasDateTimeOriginal 2024-06-17 21:41:37 -07:00
a9275dd5d1 Pending changes 2024-06-17 21:01:57 -07:00
dc1b0e3efd LogInformation 2024-05-21 18:59:37 -07:00
2661c4174c Bump 2024-05-21 18:57:49 -07:00
9521aee8c6 InPlace 2024-05-21 18:56:47 -07:00
b9ed5ee159 JsonSerializer.Deserialize for AppSettings 2024-05-21 16:23:45 -07:00
cd88e340a3 Format
Try when running synchronously
2024-05-19 22:30:33 -07:00
18 changed files with 198 additions and 377 deletions

View File

@ -119,7 +119,7 @@ dotnet_diagnostic.IDE0048.severity = error # Parentheses preferences (IDE0047 an
dotnet_diagnostic.IDE0049.severity = warning # Use language keywords instead of framework type names for type references (IDE0049) dotnet_diagnostic.IDE0049.severity = warning # Use language keywords instead of framework type names for type references (IDE0049)
dotnet_diagnostic.IDE0051.severity = error # Private member '' is unused [, ] dotnet_diagnostic.IDE0051.severity = error # Private member '' is unused [, ]
dotnet_diagnostic.IDE0060.severity = warning # IDE0060: Remove unused parameter dotnet_diagnostic.IDE0060.severity = warning # IDE0060: Remove unused parameter
dotnet_diagnostic.IDE0130.severity = error # Namespace does not match folder structure (IDE0130) dotnet_diagnostic.IDE0130.severity = none # Namespace does not match folder structure (IDE0130)
dotnet_diagnostic.IDE0230.severity = warning # IDE0230: Use UTF-8 string literal dotnet_diagnostic.IDE0230.severity = warning # IDE0230: Use UTF-8 string literal
dotnet_diagnostic.IDE0290.severity = error # Use primary constructor [Distance]csharp(IDE0290) dotnet_diagnostic.IDE0290.severity = error # Use primary constructor [Distance]csharp(IDE0290)
dotnet_diagnostic.IDE0300.severity = error # IDE0300: Collection initialization can be simplified dotnet_diagnostic.IDE0300.severity = error # IDE0300: Collection initialization can be simplified

View File

@ -34,7 +34,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="MetadataExtractor" Version="2.8.1" /> <PackageReference Include="MetadataExtractor" Version="2.8.1" />
<PackageReference Include="System.Text.Json" Version="8.0.3" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,2 +0,0 @@
[*.cs]
csharp_preserve_single_line_statements = true

View File

@ -1,82 +0,0 @@
using Microsoft.Extensions.Configuration;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Metadata.Models.Binder;
public class MetadataConfiguration
{
public bool? ForceMetadataLastWriteTimeToCreationTime { get; set; }
public string[]? IgnoreRulesKeyWords { get; set; }
public int? IntMinValueLength { get; set; }
public int? Offset { get; set; }
public bool? PropertiesChangedForMetadata { get; set; }
public override string ToString()
{
string result = JsonSerializer.Serialize(this, BinderMetadataConfigurationSourceGenerationContext.Default.MetadataConfiguration);
return result;
}
private static void PreVerify(IConfigurationRoot configurationRoot, MetadataConfiguration? configuration)
{
if (configuration?.ForceMetadataLastWriteTimeToCreationTime is null)
{
List<string> paths = [];
foreach (IConfigurationProvider configurationProvider in configurationRoot.Providers)
{
if (configurationProvider is not Microsoft.Extensions.Configuration.Json.JsonConfigurationProvider jsonConfigurationProvider)
continue;
if (jsonConfigurationProvider.Source.FileProvider is not Microsoft.Extensions.FileProviders.PhysicalFileProvider physicalFileProvider)
continue;
paths.Add(physicalFileProvider.Root);
}
throw new NotSupportedException($"Not found!{Environment.NewLine}{string.Join(Environment.NewLine, paths.Distinct())}");
}
}
private static void Verify(MetadataConfiguration configuration)
{
if (configuration.IntMinValueLength is null || configuration.IntMinValueLength != int.MinValue.ToString().Length) throw new NotSupportedException(nameof(configuration.IgnoreRulesKeyWords));
if (configuration.IgnoreRulesKeyWords is null || configuration.IgnoreRulesKeyWords.Length == 0) throw new NullReferenceException(nameof(configuration.IgnoreRulesKeyWords));
}
private static Shared.Models.MetadataConfiguration Get(MetadataConfiguration? configuration, Shared.Models.ResultConfiguration resultConfiguration)
{
Shared.Models.MetadataConfiguration result;
if (configuration is null) throw new NullReferenceException(nameof(configuration));
if (configuration.ForceMetadataLastWriteTimeToCreationTime is null) throw new NullReferenceException(nameof(configuration.ForceMetadataLastWriteTimeToCreationTime));
if (configuration.IntMinValueLength is null) throw new NullReferenceException(nameof(configuration.IntMinValueLength));
if (configuration.IgnoreRulesKeyWords is null) throw new NullReferenceException(nameof(configuration.IgnoreRulesKeyWords));
if (configuration.Offset is null) throw new NullReferenceException(nameof(configuration.Offset));
if (configuration.PropertiesChangedForMetadata is null) throw new NullReferenceException(nameof(configuration.PropertiesChangedForMetadata));
Verify(configuration);
result = new(resultConfiguration,
configuration.ForceMetadataLastWriteTimeToCreationTime.Value,
configuration.IgnoreRulesKeyWords,
configuration.IntMinValueLength.Value,
configuration.Offset.Value,
configuration.PropertiesChangedForMetadata.Value);
return result;
}
public static Shared.Models.MetadataConfiguration Get(IConfigurationRoot configurationRoot, Shared.Models.ResultConfiguration resultConfiguration)
{
Shared.Models.MetadataConfiguration result;
IConfigurationSection configurationSection = configurationRoot.GetSection(nameof(Shared.Models.MetadataConfiguration));
#pragma warning disable IL3050, IL2026
MetadataConfiguration? configuration = configurationSection.Get<MetadataConfiguration>();
#pragma warning restore IL3050, IL2026
PreVerify(configurationRoot, configuration);
result = Get(configuration, resultConfiguration);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(MetadataConfiguration))]
internal partial class BinderMetadataConfigurationSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -1,99 +0,0 @@
using Microsoft.Extensions.Configuration;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Metadata.Models.Binder;
public class ResultConfiguration
{
public string? DateGroup { get; set; }
public int? EpicYear { get; set; }
public string? ModelName { get; set; }
public int? NumberOfJitters { get; set; }
public int? NumberOfTimesToUpsample { get; set; }
public string? PredictorModelName { get; set; }
public int? ResultAllInOneSubdirectoryLength { get; set; }
public string? ResultCollection { get; set; }
public string? ResultContent { get; set; }
public string? ResultSingleton { get; set; }
public string? RootDirectory { get; set; }
public override string ToString()
{
string result = JsonSerializer.Serialize(this, BinderResultConfigurationSourceGenerationContext.Default.ResultConfiguration);
return result;
}
private static void PreVerify(IConfigurationRoot configurationRoot, ResultConfiguration? configuration)
{
if (configuration?.DateGroup is null)
{
List<string> paths = [];
foreach (IConfigurationProvider configurationProvider in configurationRoot.Providers)
{
if (configurationProvider is not Microsoft.Extensions.Configuration.Json.JsonConfigurationProvider jsonConfigurationProvider)
continue;
if (jsonConfigurationProvider.Source.FileProvider is not Microsoft.Extensions.FileProviders.PhysicalFileProvider physicalFileProvider)
continue;
paths.Add(physicalFileProvider.Root);
}
throw new NotSupportedException($"Not found!{Environment.NewLine}{string.Join(Environment.NewLine, paths.Distinct())}");
}
}
public static void Verify(ResultConfiguration configuration, bool requireRootDirectoryExists)
{
if (string.IsNullOrEmpty(configuration.DateGroup)) throw new NullReferenceException(nameof(configuration.DateGroup));
if (string.IsNullOrEmpty(configuration.RootDirectory) || (requireRootDirectoryExists && !Directory.Exists(configuration.RootDirectory))) throw new NullReferenceException(nameof(configuration.RootDirectory));
}
private static Shared.Models.ResultConfiguration Get(ResultConfiguration? configuration, bool requireRootDirectoryExists)
{
Shared.Models.ResultConfiguration result;
if (configuration is null) throw new NullReferenceException(nameof(configuration));
if (configuration.DateGroup is null) throw new NullReferenceException(nameof(configuration.DateGroup));
if (configuration.EpicYear is null) throw new NullReferenceException(nameof(configuration.EpicYear));
// if (configuration.ModelName is null) throw new NullReferenceException(nameof(configuration.ModelName));
// if (configuration.NumberOfJitters is null) throw new NullReferenceException(nameof(configuration.NumberOfJitters));
// if (configuration.NumberOfTimesToUpsample is null) throw new NullReferenceException(nameof(configuration.NumberOfTimesToUpsample));
// if (configuration.PredictorModelName is null) throw new NullReferenceException(nameof(configuration.PredictorModelName));
if (configuration.ResultAllInOneSubdirectoryLength is null) throw new NullReferenceException(nameof(configuration.ResultAllInOneSubdirectoryLength));
if (configuration.ResultCollection is null) throw new NullReferenceException(nameof(configuration.ResultCollection));
if (configuration.ResultContent is null) throw new NullReferenceException(nameof(configuration.ResultContent));
if (configuration.ResultSingleton is null) throw new NullReferenceException(nameof(configuration.ResultSingleton));
if (configuration.RootDirectory is null) throw new NullReferenceException(nameof(configuration.RootDirectory));
Verify(configuration, requireRootDirectoryExists);
result = new(configuration.DateGroup,
configuration.EpicYear.Value,
configuration.ModelName,
configuration.NumberOfJitters,
configuration.NumberOfTimesToUpsample,
configuration.PredictorModelName,
configuration.ResultAllInOneSubdirectoryLength.Value,
configuration.ResultCollection,
configuration.ResultContent,
configuration.ResultSingleton,
Path.GetFullPath(configuration.RootDirectory));
return result;
}
public static Shared.Models.ResultConfiguration Get(IConfigurationRoot configurationRoot, bool requireRootDirectoryExists)
{
Shared.Models.ResultConfiguration result;
IConfigurationSection configurationSection = configurationRoot.GetSection(nameof(Shared.Models.ResultConfiguration));
#pragma warning disable IL3050, IL2026
ResultConfiguration? configuration = configurationSection.Get<ResultConfiguration>();
#pragma warning restore IL3050, IL2026
PreVerify(configurationRoot, configuration);
result = Get(configuration, requireRootDirectoryExists);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(ResultConfiguration))]
internal partial class BinderResultConfigurationSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -47,9 +47,9 @@ internal abstract class GPS
Math.Asin(Math.Min(1, Math.Asin(Math.Min(1,
Math.Sqrt( Math.Sqrt(
Math.Pow(Math.Sin(DiffRadian(originLatitude, destinationLatitude) / 2.0), 2.0) + Math.Pow(Math.Sin(DiffRadian(originLatitude, destinationLatitude) / 2.0), 2.0) +
Math.Cos(ToRadian(originLatitude)) * Math.Cos(ToRadian(destinationLatitude)) * (Math.Cos(ToRadian(originLatitude)) * Math.Cos(ToRadian(destinationLatitude)) *
Math.Pow(Math.Sin(DiffRadian(originLongitude, destinationLongitude) / 2.0), Math.Pow(Math.Sin(DiffRadian(originLongitude, destinationLongitude) / 2.0),
2.0)))), decimalPlaces); 2.0))))), decimalPlaces);
} }
private static double ParseValueFromDmsString(string value) private static double ParseValueFromDmsString(string value)

View File

@ -46,7 +46,7 @@ internal static class Get
string key = $"{Path.Combine(fileHolder.DirectoryName ?? throw new NotSupportedException(), fileHolder.NameWithoutExtension)}"; string key = $"{Path.Combine(fileHolder.DirectoryName ?? throw new NotSupportedException(), fileHolder.NameWithoutExtension)}";
if (distinct.Contains(key)) if (distinct.Contains(key))
throw new NotSupportedException("Turn off parallelism when sidecar files are present!"); throw new NotSupportedException("Turn off parallelism when sidecar files are present!");
if (!renameConfiguration.SkipIdFiles || filePath.Id is null || !filePath.IsIntelligentIdFormat && filePath.SortOrder is not null) if (!renameConfiguration.SkipIdFiles || filePath.Id is null || (!filePath.IsIntelligentIdFormat && filePath.SortOrder is not null))
{ {
if (filePath.Id is not null) if (filePath.Id is not null)
{ {

View File

@ -35,7 +35,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CliWrap" Version="3.6.6" /> <PackageReference Include="CliWrap" Version="3.6.6" />
<PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="8.0.4" /> <PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="8.0.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />

View File

@ -3,7 +3,8 @@ using System.Text.Json.Serialization;
namespace View_by_Distance.Rename.Models; namespace View_by_Distance.Rename.Models;
public record AppSettings(string Company, public record AppSettings(RenameConfiguration RenameConfiguration,
string Company,
int MaxDegreeOfParallelism, int MaxDegreeOfParallelism,
bool RequireRootDirectoryExists) bool RequireRootDirectoryExists)
{ {

View File

@ -8,6 +8,9 @@ public class AppSettings
{ {
public string? Company { get; set; } public string? Company { get; set; }
public string[]? ConfigurationDirectoryNames { get; set; }
public string? ConfigurationFileName { get; set; }
public int? ConfigurationSpecialFolder { get; set; }
public int? MaxDegreeOfParallelism { get; set; } public int? MaxDegreeOfParallelism { get; set; }
public bool? RequireRootDirectoryExists { get; set; } public bool? RequireRootDirectoryExists { get; set; }
@ -34,21 +37,54 @@ public class AppSettings
} }
} }
private static void Verify(AppSettings _) private static void Verify(Models.AppSettings appSettings)
{ {
if (appSettings.MaxDegreeOfParallelism > 1 && (appSettings.RenameConfiguration.InPlaceWithOriginalName || appSettings.RenameConfiguration.InPlace))
throw new NotSupportedException($"Change configuration: {nameof(appSettings.RenameConfiguration.InPlace)} or {nameof(appSettings.MaxDegreeOfParallelism)}");
if (appSettings.RenameConfiguration.InPlaceWithOriginalName && appSettings.RenameConfiguration.InPlace)
throw new NotSupportedException($"Change configuration: {nameof(appSettings.RenameConfiguration.InPlace)} or {nameof(appSettings.RenameConfiguration.InPlaceWithOriginalName)}");
} }
private static Models.AppSettings Get(AppSettings? appSettings) private static Models.AppSettings Get(AppSettings? appSettings, RenameConfiguration renameConfiguration)
{ {
Models.AppSettings result; Models.AppSettings result;
if (appSettings is null) throw new NullReferenceException(nameof(appSettings)); if (appSettings is null) throw new NullReferenceException(nameof(appSettings));
if (appSettings.Company is null) throw new NullReferenceException(nameof(appSettings.Company)); if (appSettings.Company is null) throw new NullReferenceException(nameof(appSettings.Company));
if (appSettings.MaxDegreeOfParallelism is null) throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); if (appSettings.MaxDegreeOfParallelism is null) throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism));
if (appSettings.RequireRootDirectoryExists is null) throw new NullReferenceException(nameof(appSettings.RequireRootDirectoryExists)); if (appSettings.RequireRootDirectoryExists is null) throw new NullReferenceException(nameof(appSettings.RequireRootDirectoryExists));
Verify(appSettings); result = new(renameConfiguration,
result = new(appSettings.Company, appSettings.Company,
appSettings.MaxDegreeOfParallelism.Value, appSettings.MaxDegreeOfParallelism.Value,
appSettings.RequireRootDirectoryExists.Value); appSettings.RequireRootDirectoryExists.Value);
Verify(result);
return result;
}
private static Models.AppSettings Get(AppSettings? appSettings)
{
Models.AppSettings? result;
string? json;
if (appSettings is null || appSettings.ConfigurationFileName is null)
throw new NotSupportedException($"{nameof(appSettings.ConfigurationFileName)} must be set!");
string jsonFile = Path.Combine(AppContext.BaseDirectory, appSettings.ConfigurationFileName);
if (File.Exists(jsonFile))
json = File.ReadAllText(jsonFile);
else
{
json = null;
string applicationData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
List<string> collection = [applicationData];
if (appSettings?.ConfigurationDirectoryNames is not null)
collection.AddRange(appSettings.ConfigurationDirectoryNames);
if (appSettings?.ConfigurationFileName is not null)
collection.Add(appSettings.ConfigurationFileName);
jsonFile = Path.Combine(collection.ToArray());
}
if (string.IsNullOrEmpty(json) && File.Exists(jsonFile))
json = File.ReadAllText(jsonFile);
result = (string.IsNullOrEmpty(json) ? null : result = JsonSerializer.Deserialize(json, AppSettingsSourceGenerationContext.Default.AppSettings)) ??
throw new NullReferenceException(nameof(Models.AppSettings));
result = Get(appSettings, result.RenameConfiguration);
return result; return result;
} }

View File

@ -1,95 +0,0 @@
using Microsoft.Extensions.Configuration;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Rename.Models.Binder;
public class RenameConfiguration
{
public string? DefaultMaker { get; set; }
public bool? ForceNewId { get; set; }
public string[]? IgnoreExtensions { get; set; }
public bool? OnlySaveIdentifiersToDisk { get; set; }
public string? RelativePropertyCollectionFile { get; set; }
public string[]? SidecarExtensions { get; set; }
public bool? SkipIdFiles { get; set; }
public string[]? ValidImageFormatExtensions { get; set; }
public string[]? ValidVideoFormatExtensions { get; set; }
public override string ToString()
{
string result = JsonSerializer.Serialize(this, BinderConfigurationSourceGenerationContext.Default.RenameConfiguration);
return result;
}
private static void PreVerify(IConfigurationRoot configurationRoot, RenameConfiguration? configuration)
{
if (configuration?.DefaultMaker is null)
{
List<string> paths = [];
foreach (IConfigurationProvider configurationProvider in configurationRoot.Providers)
{
if (configurationProvider is not Microsoft.Extensions.Configuration.Json.JsonConfigurationProvider jsonConfigurationProvider)
continue;
if (jsonConfigurationProvider.Source.FileProvider is not Microsoft.Extensions.FileProviders.PhysicalFileProvider physicalFileProvider)
continue;
paths.Add(physicalFileProvider.Root);
}
throw new NotSupportedException($"Not found!{Environment.NewLine}{string.Join(Environment.NewLine, paths.Distinct())}");
}
}
private static void Verify(RenameConfiguration configuration)
{
if (configuration.IgnoreExtensions is null || configuration.IgnoreExtensions.Length == 0) throw new NullReferenceException(nameof(configuration.IgnoreExtensions));
if (configuration.ValidImageFormatExtensions is null || configuration.ValidImageFormatExtensions.Length == 0) throw new NullReferenceException(nameof(configuration.ValidImageFormatExtensions));
if (configuration.ValidVideoFormatExtensions is null || configuration.ValidVideoFormatExtensions.Length == 0) throw new NullReferenceException(nameof(configuration.ValidVideoFormatExtensions));
}
private static Models.RenameConfiguration Get(RenameConfiguration? configuration, Shared.Models.MetadataConfiguration metadataConfiguration)
{
Models.RenameConfiguration result;
if (configuration is null) throw new NullReferenceException(nameof(configuration));
if (configuration.DefaultMaker is null) throw new NullReferenceException(nameof(configuration.DefaultMaker));
if (configuration.ForceNewId is null) throw new NullReferenceException(nameof(configuration.ForceNewId));
if (configuration.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions));
if (configuration.OnlySaveIdentifiersToDisk is null) throw new NullReferenceException(nameof(configuration.OnlySaveIdentifiersToDisk));
if (configuration.RelativePropertyCollectionFile is null) throw new NullReferenceException(nameof(configuration.RelativePropertyCollectionFile));
if (configuration.SidecarExtensions is null) throw new NullReferenceException(nameof(configuration.SidecarExtensions));
if (configuration.SkipIdFiles is null) throw new NullReferenceException(nameof(configuration.SkipIdFiles));
if (configuration.ValidImageFormatExtensions is null) throw new NullReferenceException(nameof(configuration.ValidImageFormatExtensions));
if (configuration.ValidVideoFormatExtensions is null) throw new NullReferenceException(nameof(configuration.ValidVideoFormatExtensions));
Verify(configuration);
result = new(metadataConfiguration,
configuration.DefaultMaker,
configuration.ForceNewId.Value,
configuration.IgnoreExtensions,
configuration.OnlySaveIdentifiersToDisk.Value,
configuration.RelativePropertyCollectionFile,
configuration.SidecarExtensions,
configuration.SkipIdFiles.Value,
configuration.ValidImageFormatExtensions,
configuration.ValidVideoFormatExtensions);
return result;
}
public static Models.RenameConfiguration Get(IConfigurationRoot configurationRoot, Shared.Models.MetadataConfiguration metadataConfiguration)
{
Models.RenameConfiguration result;
IConfigurationSection configurationSection = configurationRoot.GetSection(nameof(RenameConfiguration));
#pragma warning disable IL3050, IL2026
RenameConfiguration? configuration = configurationSection.Get<RenameConfiguration>();
#pragma warning restore IL3050, IL2026
PreVerify(configurationRoot, configuration);
result = Get(configuration, metadataConfiguration);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(RenameConfiguration))]
internal partial class BinderConfigurationSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -8,6 +8,8 @@ public record RenameConfiguration(Shared.Models.MetadataConfiguration MetadataCo
string DefaultMaker, string DefaultMaker,
bool ForceNewId, bool ForceNewId,
string[] IgnoreExtensions, string[] IgnoreExtensions,
bool InPlace,
bool InPlaceWithOriginalName,
bool OnlySaveIdentifiersToDisk, bool OnlySaveIdentifiersToDisk,
string RelativePropertyCollectionFile, string RelativePropertyCollectionFile,
string[] SidecarExtensions, string[] SidecarExtensions,

View File

@ -28,17 +28,17 @@ public class Program
if (args is null) if (args is null)
throw new Exception("args is null!"); throw new Exception("args is null!");
Shared.Models.Console console = new(); Shared.Models.Console console = new();
_ = new Rename(args, logger, configurationRoot, appSettings, silentIndex > -1, console); _ = new Rename(args, logger, appSettings, silentIndex > -1, console);
} }
catch (Exception ex) catch (Exception ex)
{ {
logger?.LogError(ex, "Error!"); logger?.LogError(ex, "Error!");
} }
if (silentIndex > -1) if (silentIndex > -1)
logger?.LogDebug("Done. Bye"); logger?.LogInformation("Done. Bye");
else else
{ {
logger?.LogDebug("Done. Press 'Enter' to end"); logger?.LogInformation("Done. Press 'Enter' to end");
_ = Console.ReadLine(); _ = Console.ReadLine();
} }
} }

View File

@ -1,5 +1,4 @@
using CliWrap; using CliWrap;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using ShellProgressBar; using ShellProgressBar;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@ -28,7 +27,7 @@ public partial class Rename : IRename, IDisposable
private ProgressBar? _ProgressBar; private ProgressBar? _ProgressBar;
public Rename(List<string> args, ILogger<Program>? logger, IConfigurationRoot configurationRoot, AppSettings appSettings, bool isSilent, IConsole console) public Rename(List<string> args, ILogger<Program>? logger, AppSettings appSettings, bool isSilent, IConsole console)
{ {
if (isSilent) if (isSilent)
{ } { }
@ -38,10 +37,7 @@ public partial class Rename : IRename, IDisposable
throw new NullReferenceException(nameof(console)); throw new NullReferenceException(nameof(console));
IRename rename = this; IRename rename = this;
long ticks = DateTime.Now.Ticks; long ticks = DateTime.Now.Ticks;
ResultConfiguration resultConfiguration = Metadata.Models.Binder.ResultConfiguration.Get(configurationRoot, appSettings.RequireRootDirectoryExists); RenameWork(logger, appSettings, rename, ticks);
MetadataConfiguration metadataConfiguration = Metadata.Models.Binder.MetadataConfiguration.Get(configurationRoot, resultConfiguration);
RenameConfiguration renameConfiguration = Models.Binder.RenameConfiguration.Get(configurationRoot, metadataConfiguration);
RenameWork(logger, appSettings, rename, ticks, renameConfiguration);
} }
void IRename.Tick() => void IRename.Tick() =>
@ -121,26 +117,53 @@ public partial class Rename : IRename, IDisposable
#pragma warning restore CA1416 #pragma warning restore CA1416
private static void RenameUrl(FilePath filePath) private void NonParallelismAndInPlace(RenameConfiguration renameConfiguration, ReadOnlyCollection<int> ids, ExifDirectory exifDirectory, FileInfo fileInfo, FilePath filePath, ReadOnlyCollection<FileHolder> sidecarFiles)
{ {
FileHolder fileHolder; if (exifDirectory.Id is null)
string[] lines = File.ReadAllLines(filePath.FullName); throw new NotImplementedException();
if (lines.Length == 1) int i = 0;
const string jpg = ".jpg";
const string jpeg = ".jpeg";
List<ToDo> toDoCollection = [];
DateTime? dateTime = IDate.GetDateTimeOriginal(exifDirectory);
ReadOnlyCollection<string> keywords = IMetadata.GetKeywords(exifDirectory);
MetadataConfiguration metadataConfiguration = renameConfiguration.MetadataConfiguration;
bool hasIgnoreKeyword = metadataConfiguration.IgnoreRulesKeyWords.Any(keywords.Contains);
string checkFileExtension = filePath.ExtensionLowered == jpeg ? jpg : filePath.ExtensionLowered;
bool hasDateTimeOriginal = dateTime is not null;
string paddedId = IId.GetPaddedId(metadataConfiguration, exifDirectory.Id.Value, hasIgnoreKeyword, hasDateTimeOriginal, i);
string checkDirectory = renameConfiguration.InPlaceWithOriginalName ? Path.Combine(filePath.DirectoryName, filePath.FileNameFirstSegment) : filePath.DirectoryName;
string checkFile = Path.Combine(checkDirectory, $"{paddedId}{checkFileExtension}");
if (checkFile != filePath.FullName)
{ {
fileHolder = FileHolder.Get(lines[0]); if (File.Exists(checkFile))
if (fileHolder.Exists)
{ {
string checkFile; checkFile = string.Concat(checkFile, ".del");
checkFile = IId.GetIgnoreFullPath(filePath, fileHolder); if (File.Exists(checkFile))
if (lines[0] == checkFile || lines[0].Length != checkFile.Length) throw new NotImplementedException();
throw new NotSupportedException(); }
File.Move(lines[0], checkFile); toDoCollection.Add(new(checkDirectory, filePath, checkFile, JsonFile: false));
if (sidecarFiles.Count != 0)
{
if (renameConfiguration.InPlace)
throw new NotSupportedException($"Must use {nameof(renameConfiguration.InPlaceWithOriginalName)} when sidecar file(s) are present!");
dateTime ??= IDate.GetMinimum(exifDirectory);
RecordB recordB = new(dateTime.Value, exifDirectory, filePath, sidecarFiles, hasDateTimeOriginal, hasIgnoreKeyword, fileInfo.FullName);
toDoCollection.AddRange(GetSidecarFiles(metadataConfiguration, recordB, [], checkDirectory, paddedId));
}
_ = RenameFilesInDirectories(renameConfiguration, new(toDoCollection));
string jsonFile = Path.Combine(checkDirectory, $"{paddedId}{checkFileExtension}.json");
File.Move(fileInfo.FullName, jsonFile, overwrite: true);
if (renameConfiguration.InPlaceWithOriginalName && ids.Count > 0)
{
string idCheck = Path.Combine(checkDirectory, ids.Contains(exifDirectory.Id.Value) ? "_ Exists _" : "_ New _");
if (!Directory.Exists(idCheck))
_ = Directory.CreateDirectory(idCheck);
} }
File.Delete(filePath.FullName);
} }
} }
private static List<RecordA> GetRecordACollection(IRename rename, RenameConfiguration renameConfiguration, IEnumerable<string> files, A_Metadata metadata) private List<RecordA> GetRecordACollection(ILogger<Program>? logger, RenameConfiguration renameConfiguration, IRename rename, ReadOnlyCollection<int> ids, IEnumerable<string> files, A_Metadata metadata)
{ {
List<RecordA> results = []; List<RecordA> results = [];
int index = -1; int index = -1;
@ -167,17 +190,14 @@ public partial class Rename : IRename, IDisposable
if (renameConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered)) if (renameConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered))
continue; continue;
filePath = FilePath.Get(renameConfiguration.MetadataConfiguration, fileHolder, index); filePath = FilePath.Get(renameConfiguration.MetadataConfiguration, fileHolder, index);
if (filePath.ExtensionLowered == ".url" && filePath.Id is not null)
{
RenameUrl(filePath);
continue;
}
if (renameConfiguration.SkipIdFiles && filePath.Id is not null && (filePath.IsIntelligentIdFormat || filePath.SortOrder is not null)) if (renameConfiguration.SkipIdFiles && filePath.Id is not null && (filePath.IsIntelligentIdFormat || filePath.SortOrder is not null))
continue; continue;
if (!renameConfiguration.ForceNewId && filePath.Id is not null) if (!renameConfiguration.ForceNewId && filePath.Id is not null)
{ {
ffmpegFiles = null; ffmpegFiles = null;
deterministicHashCode = new(null, filePath.Id, null); deterministicHashCode = new(null, filePath.Id, null);
if (renameConfiguration.InPlaceWithOriginalName || (renameConfiguration.InPlace && filePath.DirectoryName.EndsWith(filePath.Id.Value.ToString())))
continue;
} }
else else
{ {
@ -192,13 +212,21 @@ public partial class Rename : IRename, IDisposable
continue; continue;
sidecarFiles.Add(keyValuePair.Value[i]); sidecarFiles.Add(keyValuePair.Value[i]);
} }
(fileInfo, exifDirectory) = metadata.GetMetadataCollection(renameConfiguration.MetadataConfiguration, filePath, deterministicHashCode); try
results.Add(new(exifDirectory, fileInfo, filePath, new(sidecarFiles))); { (fileInfo, exifDirectory) = metadata.GetMetadataCollection(renameConfiguration.MetadataConfiguration, filePath, deterministicHashCode); }
catch (Exception)
{
logger?.LogWarning("<{filePath}>", filePath.FullName);
continue;
}
if (ffmpegFiles is not null) if (ffmpegFiles is not null)
{ {
foreach (string ffmpegFile in ffmpegFiles) foreach (string ffmpegFile in ffmpegFiles)
File.Delete(ffmpegFile); File.Delete(ffmpegFile);
} }
if (renameConfiguration.InPlace || renameConfiguration.InPlaceWithOriginalName)
NonParallelismAndInPlace(renameConfiguration, ids, exifDirectory, fileInfo, filePath, new(sidecarFiles));
results.Add(new(exifDirectory, fileInfo, filePath, new(sidecarFiles)));
} }
} }
return results; return results;
@ -223,17 +251,18 @@ public partial class Rename : IRename, IDisposable
return new(results); return new(results);
} }
private ReadOnlyCollection<RecordB> GetRecordBCollection(IRename rename, AppSettings appSettings, RenameConfiguration renameConfiguration, DirectoryInfo directoryInfo) private ReadOnlyCollection<RecordB> GetRecordBCollection(ILogger<Program>? logger, AppSettings appSettings, IRename rename, ReadOnlyCollection<int> ids, DirectoryInfo directoryInfo)
{ {
ReadOnlyCollection<RecordB> results; ReadOnlyCollection<RecordB> results;
List<RecordA> recordACollection = []; List<RecordA> recordACollection = [];
RenameConfiguration renameConfiguration = appSettings.RenameConfiguration;
A_Metadata metadata = new(renameConfiguration.MetadataConfiguration); A_Metadata metadata = new(renameConfiguration.MetadataConfiguration);
int appSettingsMaxDegreeOfParallelism = appSettings.MaxDegreeOfParallelism; int appSettingsMaxDegreeOfParallelism = appSettings.MaxDegreeOfParallelism;
IEnumerable<string> files = appSettingsMaxDegreeOfParallelism == 1 ? Directory.GetFiles(directoryInfo.FullName, "*", SearchOption.AllDirectories) : Directory.EnumerateFiles(directoryInfo.FullName, "*", SearchOption.AllDirectories); IEnumerable<string> files = appSettingsMaxDegreeOfParallelism == 1 ? Directory.GetFiles(directoryInfo.FullName, "*", SearchOption.AllDirectories) : Directory.EnumerateFiles(directoryInfo.FullName, "*", SearchOption.AllDirectories);
int filesCount = appSettingsMaxDegreeOfParallelism == 1 ? files.Count() : 123000; int filesCount = appSettingsMaxDegreeOfParallelism == 1 ? files.Count() : 123000;
_ProgressBar = new(filesCount, "EnumerateFiles load", new ProgressBarOptions() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }); _ProgressBar = new(filesCount, "EnumerateFiles load", new ProgressBarOptions() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true });
if (appSettingsMaxDegreeOfParallelism == 1) if (appSettingsMaxDegreeOfParallelism == 1)
recordACollection.AddRange(GetRecordACollection(rename, renameConfiguration, files, metadata)); recordACollection.AddRange(GetRecordACollection(logger, renameConfiguration, rename, ids, files, metadata));
else else
{ {
List<string> distinct = []; List<string> distinct = [];
@ -277,7 +306,7 @@ public partial class Rename : IRename, IDisposable
string splat = filePath.DirectoryName[^3..][1] == '!' ? filePath.DirectoryName[^3..] : string.Empty; string splat = filePath.DirectoryName[^3..][1] == '!' ? filePath.DirectoryName[^3..] : string.Empty;
string makerSplit = string.IsNullOrEmpty(maker) ? string.IsNullOrEmpty(renameConfiguration.DefaultMaker) ? string.Empty : renameConfiguration.DefaultMaker : $" {maker.Split(' ')[0]}"; string makerSplit = string.IsNullOrEmpty(maker) ? string.IsNullOrEmpty(renameConfiguration.DefaultMaker) ? string.Empty : renameConfiguration.DefaultMaker : $" {maker.Split(' ')[0]}";
string directoryName = $"{year}.{seasonValue} {seasonName}{makerSplit}{splat}"; string directoryName = $"{year}.{seasonValue} {seasonName}{makerSplit}{splat}";
result = Path.Combine(renameConfiguration.MetadataConfiguration.ResultConfiguration.RootDirectory, record.ExifDirectory.Id is null || !ids.Contains(record.ExifDirectory.Id.Value) ? "_ Destination _" : "_ Exists _", record.HasDateTimeOriginal ? "Has" : "Not", directoryName); result = Path.Combine(renameConfiguration.MetadataConfiguration.ResultConfiguration.RootDirectory, record.ExifDirectory.Id is null || ids.Contains(record.ExifDirectory.Id.Value) ? "_ Exists _" : "_ New-Destination _", record.HasDateTimeOriginal ? "Has" : "Not", directoryName);
} }
return result; return result;
} }
@ -309,7 +338,26 @@ public partial class Rename : IRename, IDisposable
return results; return results;
} }
private static ReadOnlyCollection<ToDo> GetToDoCollection(RenameConfiguration renameConfiguration, Identifier[]? identifiers, ReadOnlyCollection<RecordB> recordBCollection) private static bool? GetDirectoryCheck(RenameConfiguration renameConfiguration)
{
bool? result = null;
foreach (string directory in Directory.GetDirectories(renameConfiguration.MetadataConfiguration.ResultConfiguration.RootDirectory, "*", SearchOption.TopDirectoryOnly))
{
foreach (string _ in Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories))
{
if (result is null)
result = false;
else if (result.Value)
result = true;
break;
}
if (result is not null && result.Value)
break;
}
return result;
}
private static ReadOnlyCollection<ToDo> GetToDoCollection(RenameConfiguration renameConfiguration, ReadOnlyCollection<int> ids, ReadOnlyCollection<RecordB> recordBCollection)
{ {
List<ToDo> results = []; List<ToDo> results = [];
RecordB record; RecordB record;
@ -323,27 +371,12 @@ public partial class Rename : IRename, IDisposable
const string jpg = ".jpg"; const string jpg = ".jpg";
string checkFileExtension; string checkFileExtension;
List<string> distinct = []; List<string> distinct = [];
bool? directoryCheck = null;
const string jpeg = ".jpeg"; const string jpeg = ".jpeg";
string jsonFileSubDirectory; string jsonFileSubDirectory;
bool multipleDirectoriesWithFiles; bool? directoryCheck = GetDirectoryCheck(renameConfiguration);
foreach (string directory in Directory.GetDirectories(renameConfiguration.MetadataConfiguration.ResultConfiguration.RootDirectory, "*", SearchOption.TopDirectoryOnly)) MetadataConfiguration metadataConfiguration = renameConfiguration.MetadataConfiguration;
{ VerifyIntMinValueLength(metadataConfiguration, recordBCollection);
foreach (string _ in Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories)) bool multipleDirectoriesWithFiles = directoryCheck is not null && directoryCheck.Value;
{
if (directoryCheck is null)
directoryCheck = false;
else if (directoryCheck.Value)
directoryCheck = true;
break;
}
if (directoryCheck is not null && directoryCheck.Value)
break;
}
VerifyIntMinValueLength(renameConfiguration.MetadataConfiguration, recordBCollection);
multipleDirectoriesWithFiles = directoryCheck is not null && directoryCheck.Value;
ResultConfiguration resultConfiguration = renameConfiguration.MetadataConfiguration.ResultConfiguration;
ReadOnlyCollection<int> ids = identifiers is null ? new([]) : new((from l in identifiers select l.Id).ToArray());
ReadOnlyCollection<RecordB> sorted = new((from l in recordBCollection orderby l.DateTime select l).ToArray()); ReadOnlyCollection<RecordB> sorted = new((from l in recordBCollection orderby l.DateTime select l).ToArray());
for (int i = 0; i < sorted.Count; i++) for (int i = 0; i < sorted.Count; i++)
{ {
@ -356,7 +389,7 @@ public partial class Rename : IRename, IDisposable
if (string.IsNullOrEmpty(checkDirectory)) if (string.IsNullOrEmpty(checkDirectory))
continue; continue;
checkFileExtension = record.FilePath.ExtensionLowered == jpeg ? jpg : record.FilePath.ExtensionLowered; checkFileExtension = record.FilePath.ExtensionLowered == jpeg ? jpg : record.FilePath.ExtensionLowered;
paddedId = IId.GetPaddedId(renameConfiguration.MetadataConfiguration, record.ExifDirectory.Id.Value, record.HasIgnoreKeyword, i); paddedId = IId.GetPaddedId(metadataConfiguration, record.ExifDirectory.Id.Value, record.HasIgnoreKeyword, record.HasDateTimeOriginal, i);
jsonFileSubDirectory = Path.GetDirectoryName(Path.GetDirectoryName(record.JsonFile)) ?? throw new Exception(); jsonFileSubDirectory = Path.GetDirectoryName(Path.GetDirectoryName(record.JsonFile)) ?? throw new Exception();
checkFile = Path.Combine(checkDirectory, $"{paddedId}{checkFileExtension}"); checkFile = Path.Combine(checkDirectory, $"{paddedId}{checkFileExtension}");
if (checkFile == record.FilePath.FullName) if (checkFile == record.FilePath.FullName)
@ -367,12 +400,12 @@ public partial class Rename : IRename, IDisposable
if (File.Exists(checkFile)) if (File.Exists(checkFile))
continue; continue;
} }
(directoryName, _) = IPath.GetDirectoryNameAndIndex(resultConfiguration, record.ExifDirectory.Id.Value); (directoryName, _) = IPath.GetDirectoryNameAndIndex(metadataConfiguration.ResultConfiguration, record.ExifDirectory.Id.Value);
jsonFile = Path.Combine(jsonFileSubDirectory, directoryName, $"{record.ExifDirectory.Id.Value}{checkFileExtension}.json"); jsonFile = Path.Combine(jsonFileSubDirectory, directoryName, $"{record.ExifDirectory.Id.Value}{checkFileExtension}.json");
if (record.JsonFile != jsonFile) if (record.JsonFile != jsonFile)
{ {
fileHolder = FileHolder.Get(record.JsonFile); fileHolder = FileHolder.Get(record.JsonFile);
filePath = FilePath.Get(renameConfiguration.MetadataConfiguration, fileHolder, index: null); filePath = FilePath.Get(metadataConfiguration, fileHolder, index: null);
results.Add(new(null, filePath, jsonFile, JsonFile: true)); results.Add(new(null, filePath, jsonFile, JsonFile: true));
} }
if (distinct.Contains(checkFile)) if (distinct.Contains(checkFile))
@ -381,7 +414,7 @@ public partial class Rename : IRename, IDisposable
results.Add(new(checkDirectory, record.FilePath, checkFile, JsonFile: false)); results.Add(new(checkDirectory, record.FilePath, checkFile, JsonFile: false));
if (record.SidecarFiles.Count == 0) if (record.SidecarFiles.Count == 0)
continue; continue;
results.AddRange(GetSidecarFiles(renameConfiguration.MetadataConfiguration, record, distinct, checkDirectory, paddedId)); results.AddRange(GetSidecarFiles(metadataConfiguration, record, distinct, checkDirectory, paddedId));
} }
return new(results); return new(results);
} }
@ -399,14 +432,17 @@ public partial class Rename : IRename, IDisposable
} }
} }
private ReadOnlyCollection<string> RenameFilesInDirectories(ReadOnlyCollection<ToDo> toDoCollection) private ReadOnlyCollection<string> RenameFilesInDirectories(RenameConfiguration renameConfiguration, ReadOnlyCollection<ToDo> toDoCollection)
{ {
List<string> results = []; List<string> results = [];
VerifyDirectories(toDoCollection); VerifyDirectories(toDoCollection);
_ProgressBar = new(toDoCollection.Count, "Move Files", new ProgressBarOptions() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }); bool useProgressBar = !renameConfiguration.InPlace && !renameConfiguration.InPlaceWithOriginalName;
if (useProgressBar)
_ProgressBar = new(toDoCollection.Count, "Move Files", new ProgressBarOptions() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true });
foreach (ToDo toDo in toDoCollection) foreach (ToDo toDo in toDoCollection)
{ {
_ProgressBar.Tick(); if (useProgressBar)
_ProgressBar?.Tick();
if (toDo.JsonFile) if (toDo.JsonFile)
{ {
if (File.Exists(toDo.File)) if (File.Exists(toDo.File))
@ -426,41 +462,60 @@ public partial class Rename : IRename, IDisposable
results.Add($"{toDo.FilePath.FullName}\t{toDo.File}"); results.Add($"{toDo.FilePath.FullName}\t{toDo.File}");
} }
} }
_ProgressBar.Dispose(); if (useProgressBar)
_ProgressBar?.Dispose();
return new(results); return new(results);
} }
private static void SaveIdentifiersToDisk(long ticks, RenameConfiguration renameConfiguration, string aMetadataCollectionDirectory, ReadOnlyCollection<RecordB> recordBCollection) private static void SaveIdentifiersToDisk(long ticks, RenameConfiguration renameConfiguration, ReadOnlyCollection<RecordB> recordBCollection)
{ {
string paddedId; string paddedId;
List<Identifier> identifiers = []; List<Identifier> identifiers = [];
MetadataConfiguration metadataConfiguration = renameConfiguration.MetadataConfiguration;
string aMetadataCollectionDirectory = IResult.GetResultsDateGroupDirectory(metadataConfiguration.ResultConfiguration, nameof(A_Metadata), metadataConfiguration.ResultConfiguration.ResultCollection);
foreach (RecordB record in recordBCollection) foreach (RecordB record in recordBCollection)
{ {
if (record.ExifDirectory.Id is null) if (record.ExifDirectory.Id is null)
continue; continue;
paddedId = IId.GetPaddedId(renameConfiguration.MetadataConfiguration, record.ExifDirectory.Id.Value, record.FilePath.IsIgnore, index: null); paddedId = IId.GetPaddedId(renameConfiguration.MetadataConfiguration, record.ExifDirectory.Id.Value, record.HasIgnoreKeyword, record.HasDateTimeOriginal, index: null);
identifiers.Add(new(record.ExifDirectory.Id.Value, record.FilePath.Length, paddedId, record.DateTime.Ticks)); identifiers.Add(new(record.ExifDirectory.Id.Value, record.FilePath.Length, paddedId, record.DateTime.Ticks));
} }
string json = JsonSerializer.Serialize(identifiers.OrderBy(l => l.PaddedId).ToArray(), IdentifierCollectionSourceGenerationContext.Default.IdentifierArray); string json = JsonSerializer.Serialize(identifiers.OrderBy(l => l.PaddedId).ToArray(), IdentifierCollectionSourceGenerationContext.Default.IdentifierArray);
_ = IPath.WriteAllText(Path.Combine(aMetadataCollectionDirectory, $"{ticks}.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null); _ = IPath.WriteAllText(Path.Combine(aMetadataCollectionDirectory, $"{ticks}.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
} }
private void RenameWork(ILogger<Program>? logger, AppSettings appSettings, IRename rename, long ticks, RenameConfiguration renameConfiguration) private static ReadOnlyCollection<int> GetIds(RenameConfiguration renameConfiguration)
{ {
string aMetadataCollectionDirectory = IResult.GetResultsDateGroupDirectory(renameConfiguration.MetadataConfiguration.ResultConfiguration, nameof(A_Metadata), renameConfiguration.MetadataConfiguration.ResultConfiguration.ResultCollection); ReadOnlyCollection<int> results;
string? propertyCollectionFile = string.IsNullOrEmpty(renameConfiguration.RelativePropertyCollectionFile) ? null : Path.GetFullPath(Path.Combine(aMetadataCollectionDirectory, renameConfiguration.RelativePropertyCollectionFile)); string? propertyCollectionFile = string.IsNullOrEmpty(renameConfiguration.RelativePropertyCollectionFile) ? null : renameConfiguration.RelativePropertyCollectionFile;
string? json = !File.Exists(propertyCollectionFile) ? null : File.ReadAllText(propertyCollectionFile); string? json = !File.Exists(propertyCollectionFile) ? null : File.ReadAllText(propertyCollectionFile);
Identifier[]? identifiers = json is null ? null : JsonSerializer.Deserialize(json, IdentifierCollectionSourceGenerationContext.Default.IdentifierArray); Identifier[]? identifiers = json is null ? null : JsonSerializer.Deserialize(json, IdentifierCollectionSourceGenerationContext.Default.IdentifierArray);
if (identifiers is null && !string.IsNullOrEmpty(renameConfiguration.RelativePropertyCollectionFile)) if (identifiers is null && !string.IsNullOrEmpty(renameConfiguration.RelativePropertyCollectionFile))
throw new Exception($"Invalid {nameof(renameConfiguration.RelativePropertyCollectionFile)}"); throw new Exception($"Invalid {nameof(renameConfiguration.RelativePropertyCollectionFile)}");
DirectoryInfo directoryInfo = new(Path.GetFullPath(renameConfiguration.MetadataConfiguration.ResultConfiguration.RootDirectory)); results = identifiers is null ? new([]) : new((from l in identifiers select l.Id).ToArray());
return results;
}
private void RenameWork(ILogger<Program>? logger, AppSettings appSettings, IRename rename, long ticks)
{
ReadOnlyCollection<int> ids = GetIds(appSettings.RenameConfiguration);
RenameConfiguration renameConfiguration = appSettings.RenameConfiguration;
MetadataConfiguration metadataConfiguration = renameConfiguration.MetadataConfiguration;
DirectoryInfo directoryInfo = new(Path.GetFullPath(metadataConfiguration.ResultConfiguration.RootDirectory));
logger?.LogInformation("{Ticks} {RootDirectory}", ticks, directoryInfo.FullName); logger?.LogInformation("{Ticks} {RootDirectory}", ticks, directoryInfo.FullName);
ReadOnlyCollection<RecordB> recordBCollection = GetRecordBCollection(rename, appSettings, renameConfiguration, directoryInfo); ReadOnlyCollection<RecordB> recordBCollection = GetRecordBCollection(logger, appSettings, rename, ids, directoryInfo);
SaveIdentifiersToDisk(ticks, renameConfiguration, aMetadataCollectionDirectory, recordBCollection); SaveIdentifiersToDisk(ticks, renameConfiguration, recordBCollection);
if (renameConfiguration.InPlace || renameConfiguration.InPlaceWithOriginalName)
{
if (recordBCollection.Count > 0)
recordBCollection = new([]);
string aMetadataSingletonDirectory = IResult.GetResultsGroupDirectory(metadataConfiguration.ResultConfiguration, nameof(A_Metadata));
_ = IPath.DeleteEmptyDirectories(aMetadataSingletonDirectory);
}
if (!renameConfiguration.OnlySaveIdentifiersToDisk) if (!renameConfiguration.OnlySaveIdentifiersToDisk)
{ {
ReadOnlyCollection<ToDo> toDoCollection = GetToDoCollection(renameConfiguration, identifiers, recordBCollection); ReadOnlyCollection<ToDo> toDoCollection = GetToDoCollection(renameConfiguration, ids, recordBCollection);
ReadOnlyCollection<string> lines = RenameFilesInDirectories(toDoCollection); ReadOnlyCollection<string> lines = RenameFilesInDirectories(renameConfiguration, toDoCollection);
if (lines.Count != 0) if (lines.Count != 0)
{ {
File.WriteAllLines($"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv", lines); File.WriteAllLines($"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv", lines);

View File

@ -32,7 +32,7 @@
<SupportedPlatform Include="browser" /> <SupportedPlatform Include="browser" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="8.0.4" /> <PackageReference Include="System.Drawing.Common" Version="8.0.8" />
<PackageReference Include="System.Text.Json" Version="8.0.3" /> <PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -10,7 +10,8 @@ public record FilePath(long CreationTicks,
string FileNameFirstSegment, string FileNameFirstSegment,
string FullName, string FullName,
int? Id, int? Id,
bool? IsIgnore, bool? HasIgnoreKeyword,
bool? HasDateTimeOriginal,
bool IsIntelligentIdFormat, bool IsIntelligentIdFormat,
long LastWriteTicks, long LastWriteTicks,
long Length, long Length,
@ -44,7 +45,8 @@ public record FilePath(long CreationTicks,
bool isIntelligentIdFormat = IId.NameWithoutExtensionIsIntelligentIdFormat(metadataConfiguration, fileNameFirstSegment); bool isIntelligentIdFormat = IId.NameWithoutExtensionIsIntelligentIdFormat(metadataConfiguration, fileNameFirstSegment);
bool isPaddedIntelligentIdFormat = IId.NameWithoutExtensionIsPaddedIntelligentIdFormat(metadataConfiguration, sortOrderOnlyLengthIndex, fileNameFirstSegment); bool isPaddedIntelligentIdFormat = IId.NameWithoutExtensionIsPaddedIntelligentIdFormat(metadataConfiguration, sortOrderOnlyLengthIndex, fileNameFirstSegment);
bool fileNameFirstSegmentIsIdFormat = !isPaddedIntelligentIdFormat && !isIntelligentIdFormat && IId.NameWithoutExtensionIsIdFormat(metadataConfiguration, fileHolder); bool fileNameFirstSegmentIsIdFormat = !isPaddedIntelligentIdFormat && !isIntelligentIdFormat && IId.NameWithoutExtensionIsIdFormat(metadataConfiguration, fileHolder);
bool? isIgnore = !isIntelligentIdFormat && !isPaddedIntelligentIdFormat ? null : fileNameFirstSegment[^1] is '2' or '8'; bool? hasIgnoreKeyword = !isIntelligentIdFormat && !isPaddedIntelligentIdFormat ? null : fileNameFirstSegment[^1] is '2' or '8';
bool? hasDateTimeOriginal = !isIntelligentIdFormat && !isPaddedIntelligentIdFormat ? null : fileNameFirstSegment[^1] is '1' or '9';
if (!fileNameFirstSegmentIsIdFormat && !isIntelligentIdFormat && !isPaddedIntelligentIdFormat) if (!fileNameFirstSegmentIsIdFormat && !isIntelligentIdFormat && !isPaddedIntelligentIdFormat)
(id, sortOder) = (null, null); (id, sortOder) = (null, null);
else if (isIntelligentIdFormat) else if (isIntelligentIdFormat)
@ -72,7 +74,8 @@ public record FilePath(long CreationTicks,
fileNameFirstSegment, fileNameFirstSegment,
fileHolder.FullName, fileHolder.FullName,
id, id,
isIgnore, hasIgnoreKeyword,
hasDateTimeOriginal,
isIntelligentIdFormat, isIntelligentIdFormat,
fileHolder.LastWriteTime.Value.Ticks, fileHolder.LastWriteTime.Value.Ticks,
fileHolder.Length.Value, fileHolder.Length.Value,

View File

@ -36,7 +36,9 @@ internal abstract class Id
return result; return result;
} }
internal static string GetIntelligentId(MetadataConfiguration metadataConfiguration, long id, bool? ignore) #pragma warning disable IDE0060
internal static string GetIntelligentId(MetadataConfiguration metadataConfiguration, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal)
#pragma warning restore IDE0060
{ {
string result; string result;
StringBuilder stringBuilder = new(); StringBuilder stringBuilder = new();
@ -47,12 +49,12 @@ internal abstract class Id
List<char> resultAllInOneSubdirectoryChars = []; List<char> resultAllInOneSubdirectoryChars = [];
if (id > -1) if (id > -1)
{ {
key = ignore is not null && ignore.Value ? 8 : 9; key = hasIgnoreKeyword is not null && hasIgnoreKeyword.Value ? 8 : 9;
value = id.ToString().PadLeft(metadataConfiguration.IntMinValueLength, '0'); value = id.ToString().PadLeft(metadataConfiguration.IntMinValueLength, '0');
} }
else else
{ {
key = ignore is not null && ignore.Value ? 2 : 1; key = hasIgnoreKeyword is not null && hasIgnoreKeyword.Value ? 2 : 1;
value = id.ToString()[1..].PadLeft(metadataConfiguration.IntMinValueLength, '0'); value = id.ToString()[1..].PadLeft(metadataConfiguration.IntMinValueLength, '0');
} }
for (int i = value.Length - metadataConfiguration.ResultConfiguration.ResultAllInOneSubdirectoryLength - 1; i > -1; i--) for (int i = value.Length - metadataConfiguration.ResultConfiguration.ResultAllInOneSubdirectoryLength - 1; i > -1; i--)
@ -63,14 +65,14 @@ internal abstract class Id
return result; return result;
} }
internal static string GetPaddedId(MetadataConfiguration metadataConfiguration, int id, bool? ignore, int? index) internal static string GetPaddedId(MetadataConfiguration metadataConfiguration, int id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal, int? index)
{ {
string result; string result;
if (metadataConfiguration.Offset < 0) if (metadataConfiguration.Offset < 0)
result = Guid.NewGuid().ToString(); result = Guid.NewGuid().ToString();
else else
{ {
string intelligentId = GetIntelligentId(metadataConfiguration, id, ignore); string intelligentId = GetIntelligentId(metadataConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal);
int check = GetId(metadataConfiguration, intelligentId); int check = GetId(metadataConfiguration, intelligentId);
if (check != id) if (check != id)
throw new NotSupportedException(); throw new NotSupportedException();

View File

@ -8,20 +8,20 @@ public interface IId
static bool IsOffsetDeterministicHashCode(MetadataConfiguration metadataConfiguration) => static bool IsOffsetDeterministicHashCode(MetadataConfiguration metadataConfiguration) =>
metadataConfiguration.Offset == DeterministicHashCode; metadataConfiguration.Offset == DeterministicHashCode;
string TestStatic_GetIntelligentId(MetadataConfiguration metadataConfiguration, long id, bool ignore) => string TestStatic_GetIntelligentId(MetadataConfiguration metadataConfiguration, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal) =>
GetIntelligentId(metadataConfiguration, id, ignore); GetIntelligentId(metadataConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal);
static string GetIntelligentId(MetadataConfiguration metadataConfiguration, long id, bool ignore) => static string GetIntelligentId(MetadataConfiguration metadataConfiguration, long id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal) =>
Id.GetIntelligentId(metadataConfiguration, id, ignore); Id.GetIntelligentId(metadataConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal);
int TestStatic_GetId(MetadataConfiguration metadataConfiguration, string intelligentId) => int TestStatic_GetId(MetadataConfiguration metadataConfiguration, string intelligentId) =>
GetId(metadataConfiguration, intelligentId); GetId(metadataConfiguration, intelligentId);
static int GetId(MetadataConfiguration metadataConfiguration, string intelligentId) => static int GetId(MetadataConfiguration metadataConfiguration, string intelligentId) =>
Id.GetId(metadataConfiguration, intelligentId); Id.GetId(metadataConfiguration, intelligentId);
string TestStatic_GetPaddedId(MetadataConfiguration metadataConfiguration, int id, bool? ignore, int? index) => string TestStatic_GetPaddedId(MetadataConfiguration metadataConfiguration, int id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal, int? index) =>
GetPaddedId(metadataConfiguration, id, ignore, index); GetPaddedId(metadataConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal, index);
static string GetPaddedId(MetadataConfiguration metadataConfiguration, int id, bool? ignore, int? index) => static string GetPaddedId(MetadataConfiguration metadataConfiguration, int id, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal, int? index) =>
Id.GetPaddedId(metadataConfiguration, id, ignore, index); Id.GetPaddedId(metadataConfiguration, id, hasIgnoreKeyword, hasDateTimeOriginal, index);
string TestStatic_GetIgnoreFullPath(FilePath filePath, FileHolder fileHolder) => string TestStatic_GetIgnoreFullPath(FilePath filePath, FileHolder fileHolder) =>
GetIgnoreFullPath(filePath, fileHolder); GetIgnoreFullPath(filePath, fileHolder);