feat: Add support for removing deleted source files
Detects files removed from the source directory, deletes the file from destination, removes it from the metadata cache.
This commit is contained in:
parent
264129b1e9
commit
da24073f14
38
Program.cs
38
Program.cs
|
|
@ -16,10 +16,8 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using Serilog.Events;
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using System.CommandLine.Builder;
|
using System.CommandLine.Builder;
|
||||||
using System.CommandLine.Help;
|
|
||||||
using System.CommandLine.Parsing;
|
using System.CommandLine.Parsing;
|
||||||
using System.CommandLine;
|
using System.CommandLine;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
@ -209,7 +207,7 @@ class Program
|
||||||
AnsiConsole.MarkupLine("[yellow]See log for more details[/]");
|
AnsiConsole.MarkupLine("[yellow]See log for more details[/]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
EnforceConsistency(settings);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -253,17 +251,37 @@ class Program
|
||||||
|
|
||||||
static void EnforceConsistency(ProjectSettings projectSettings)
|
static void EnforceConsistency(ProjectSettings projectSettings)
|
||||||
{
|
{
|
||||||
|
AnsiConsole.MarkupLine("[blue]Checking for stale files[/]");
|
||||||
// Grab the metadata.
|
// Grab the metadata.
|
||||||
|
List<string> staleMetadataFiles = new();
|
||||||
|
var metadata = SiteFile.getMetadata(projectSettings);
|
||||||
// Read the metadata.
|
// Read the metadata.
|
||||||
|
foreach (var entry in metadata)
|
||||||
|
{
|
||||||
|
var file = entry.Key;
|
||||||
|
Log.Information("Checking if {f} has been deleted", file);
|
||||||
|
if (!File.Exists(file))
|
||||||
|
{
|
||||||
|
Log.Information("{f} HAS been deleted", file);
|
||||||
|
|
||||||
// Find deleted files.
|
// what should that files new name be.
|
||||||
|
var newFileName = Conversions.GetNewName(new FileInfo(file),projectSettings);
|
||||||
// Figure out what the new name for those files would be.
|
try{
|
||||||
|
// Delete that file and mark the metadata for removal.
|
||||||
// Remove those files.
|
File.Delete(newFileName);
|
||||||
|
AnsiConsole.MarkupLineInterpolated($"[red]Deleted [blue]{newFileName}[/][/]");
|
||||||
|
Log.Information("Deleted {f}",newFileName);
|
||||||
|
staleMetadataFiles.Add(file);
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error(e,"Could not delete {f}",newFileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SiteFile.invalidateMetadata(staleMetadataFiles,projectSettings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ProjectSettings GetProjectSettings(DirectoryInfo? ProjectDirectory)
|
static ProjectSettings GetProjectSettings(DirectoryInfo? ProjectDirectory)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
10
Readme.md
10
Readme.md
|
|
@ -57,8 +57,6 @@ It only considers source files for conversion if they are new or have been
|
||||||
changed since the last run of the program.
|
changed since the last run of the program.
|
||||||
Therefore if you change the `BaseUrl` or the template file you will need to
|
Therefore if you change the `BaseUrl` or the template file you will need to
|
||||||
clean and convert your entire project.
|
clean and convert your entire project.
|
||||||
Convert also does not detect deleted source files at the moment, so you
|
|
||||||
will also need to clean for that,
|
|
||||||
|
|
||||||
#### clean
|
#### clean
|
||||||
This subcommand purges the output directory, You can of course do this
|
This subcommand purges the output directory, You can of course do this
|
||||||
|
|
@ -85,11 +83,7 @@ unless you want to structure everything to the point you only need relative
|
||||||
links. (I personally found this almost impossible)
|
links. (I personally found this almost impossible)
|
||||||
|
|
||||||
## Future plans
|
## Future plans
|
||||||
- Automatic page generation using pre-process steps and temporary files.
|
- Automatic page generation using pre-process steps and temporary files. E.G Contents pages, index pages etc...(DIFFICULT)
|
||||||
E.G Contents pages, index pages etc...(DIFFICULT)
|
|
||||||
- Detection of changes to the `BaseUrl` and any templates. (MEDIUM)
|
- Detection of changes to the `BaseUrl` and any templates. (MEDIUM)
|
||||||
- Detection of deleted source files and removal of the destination
|
|
||||||
files.(MEDIUM)
|
|
||||||
- Allow expansion of conversion operations (DIFFICULT)
|
- Allow expansion of conversion operations (DIFFICULT)
|
||||||
- Allow customisation of filetypes that can have `%BASEURL%` replaced
|
- Allow customisation of filetypes that can have `%BASEURL%` replaced (EASY-MEDIUM)
|
||||||
(EASY-MEDIUM)
|
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ public static class Conversions{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A Mapping of filetype to ConvertFunc.
|
/// A Mapping of filetype to ConvertFunc.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly Dictionary<string,ConvertFunc> Mappings = new(){
|
public static readonly Dictionary<string,(ConvertFunc function,string extension)> Mappings = new(){
|
||||||
{".md", Pandoc},
|
{".md", (Pandoc, ".html")},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly string[] StringReplaceFiletypes = {
|
private static readonly string[] StringReplaceFiletypes = {
|
||||||
|
|
@ -26,7 +26,7 @@ public static class Conversions{
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool NoOp(FileInfo file, ProjectSettings settings){
|
public static bool NoOp(FileInfo file, ProjectSettings settings){
|
||||||
Log.Information("Performing NoOp Conversion");
|
Log.Information("Performing NoOp Conversion");
|
||||||
string newName = GetNewName(file,settings,"NoOp");
|
string newName = GetNewName(file,settings);
|
||||||
Log.Debug("{FullName} -> {newName}",file.FullName,newName);
|
Log.Debug("{FullName} -> {newName}",file.FullName,newName);
|
||||||
Thread.Sleep(1500);
|
Thread.Sleep(1500);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -36,7 +36,7 @@ public static class Conversions{
|
||||||
/// Copy the file verbatim (doing any baseurl replacements if needed)
|
/// Copy the file verbatim (doing any baseurl replacements if needed)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool RawCpy(FileInfo file, ProjectSettings settings){
|
public static bool RawCpy(FileInfo file, ProjectSettings settings){
|
||||||
FileInfo newPath = new FileInfo(GetNewName(file,settings,null));
|
FileInfo newPath = new FileInfo(GetNewName(file,settings));
|
||||||
|
|
||||||
Log.Information("RawCpy: Copying {file} to {dest}",file.FullName, newPath.FullName);
|
Log.Information("RawCpy: Copying {file} to {dest}",file.FullName, newPath.FullName);
|
||||||
|
|
||||||
|
|
@ -133,11 +133,11 @@ public static class Conversions{
|
||||||
// If we have created a temporary file we need to ensure that we use it.
|
// If we have created a temporary file we need to ensure that we use it.
|
||||||
if (!string.IsNullOrEmpty(tmpFile))
|
if (!string.IsNullOrEmpty(tmpFile))
|
||||||
{
|
{
|
||||||
pandocArgs = $"{tmpFile} -o {GetNewName(file,settings,".html")}";
|
pandocArgs = $"{tmpFile} -o {GetNewName(file,settings)}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pandocArgs = $"{file.FullName} -o {GetNewName(file,settings,".html")}";
|
pandocArgs = $"{file.FullName} -o {GetNewName(file,settings)}";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (template is not null)
|
if (template is not null)
|
||||||
|
|
@ -156,9 +156,9 @@ public static class Conversions{
|
||||||
// This is used in my template to add the sitename to the title element.
|
// This is used in my template to add the sitename to the title element.
|
||||||
pandocArgs += $" --metadata=\"SiteName:{settings.SiteName}\"";
|
pandocArgs += $" --metadata=\"SiteName:{settings.SiteName}\"";
|
||||||
}
|
}
|
||||||
if (!Directory.Exists(Path.GetDirectoryName(GetNewName(file,settings,".html"))))
|
if (!Directory.Exists(Path.GetDirectoryName(GetNewName(file,settings))))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(GetNewName(file,settings,".html"))!);
|
Directory.CreateDirectory(Path.GetDirectoryName(GetNewName(file,settings))!);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pandocReturn = RunExternalProgram(pandoc,pandocArgs);
|
bool pandocReturn = RunExternalProgram(pandoc,pandocArgs);
|
||||||
|
|
@ -214,10 +214,11 @@ public static class Conversions{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetNewName(FileInfo file, ProjectSettings settings, string? newExtension){
|
public static string GetNewName(FileInfo file, ProjectSettings settings){
|
||||||
|
var newExtension = Mappings.GetValueOrDefault(file.Extension,(RawCpy,file.Extension)).extension;
|
||||||
return file.FullName
|
return file.FullName
|
||||||
.Replace(settings.InputDirectory.FullName, settings.OutputDirectory.FullName)
|
.Replace(settings.InputDirectory.FullName, settings.OutputDirectory.FullName)
|
||||||
.Replace(file.Extension,newExtension ?? file.Extension);
|
.Replace(file.Extension,newExtension);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string StringReplace(FileInfo file, ProjectSettings settings){
|
private static string StringReplace(FileInfo file, ProjectSettings settings){
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,36 @@ public partial class SiteFile
|
||||||
Conversions.ConvertFunc ConverterFunction;
|
Conversions.ConvertFunc ConverterFunction;
|
||||||
static Dictionary<string, DateTime>? Metadata = null;
|
static Dictionary<string, DateTime>? Metadata = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the metadata for the current project, loading it if not already loaded.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="settings">
|
||||||
|
/// The current <c>ProjectSettings</c>
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <c>Dictionary<string,DateTime></c> that represents the metadata stored.
|
||||||
|
/// </returns>
|
||||||
|
public static Dictionary<string,DateTime> getMetadata(ProjectSettings settings) {
|
||||||
|
if (Metadata is null)
|
||||||
|
{
|
||||||
|
LoadMetadata(settings);
|
||||||
|
}
|
||||||
|
return Metadata?? new(); // Metadata is unlikely(if not impossible) to be null here but the compiler isn't convinced
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void invalidateMetadata(List<string> files, ProjectSettings settings)
|
||||||
|
{
|
||||||
|
if (Metadata is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
files.ForEach( file => {
|
||||||
|
Metadata.Remove(file);
|
||||||
|
});
|
||||||
|
|
||||||
|
SaveMetadata(settings);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the file, Not Guaranteed to be unique.
|
/// The name of the file, Not Guaranteed to be unique.
|
||||||
/// Use only for output and logging, never file operations,
|
/// Use only for output and logging, never file operations,
|
||||||
|
|
@ -32,7 +62,7 @@ public partial class SiteFile
|
||||||
Log.Debug("{file} extension is {ext}",fileInfo.FullName, fileInfo.Extension);
|
Log.Debug("{file} extension is {ext}",fileInfo.FullName, fileInfo.Extension);
|
||||||
// Using this Ensures that the ConverterFunction is Always set.
|
// Using this Ensures that the ConverterFunction is Always set.
|
||||||
// ConverterFunctions ALWAYS accept just the FileInfo, and ProjectSettings passed at convert time.
|
// ConverterFunctions ALWAYS accept just the FileInfo, and ProjectSettings passed at convert time.
|
||||||
ConverterFunction = Conversions.Mappings.GetValueOrDefault(info.Extension, Conversions.RawCpy);
|
ConverterFunction = Conversions.Mappings.GetValueOrDefault(info.Extension, (Conversions.RawCpy,info.Extension)).function;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -88,7 +118,7 @@ public partial class SiteFile
|
||||||
* But that ensures that if you remove the output directory the site will be
|
* But that ensures that if you remove the output directory the site will be
|
||||||
* Fully recreated.
|
* Fully recreated.
|
||||||
*/
|
*/
|
||||||
private void LoadMetadata(ProjectSettings settings)
|
private static void LoadMetadata(ProjectSettings settings)
|
||||||
{
|
{
|
||||||
string metaFile = $"{settings.OutputDirectory}/.files";
|
string metaFile = $"{settings.OutputDirectory}/.files";
|
||||||
Log.Information("Loading Metadata from {file}",metaFile);
|
Log.Information("Loading Metadata from {file}",metaFile);
|
||||||
|
|
@ -114,7 +144,7 @@ public partial class SiteFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SaveMetadata(ProjectSettings settings)
|
private static void SaveMetadata(ProjectSettings settings)
|
||||||
{
|
{
|
||||||
if (Metadata is null)
|
if (Metadata is null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
3
TODO
3
TODO
|
|
@ -1,5 +1,2 @@
|
||||||
- Make the code such that the metadata file knows what source file an output file came from, this will allow us to delete files from source
|
|
||||||
and force consistency by removing them from the dst directory too.
|
|
||||||
|
|
||||||
- Add a pre-commit or other type of hook to ensure that the Testing directory is properly cleaned and reset before commit.
|
- Add a pre-commit or other type of hook to ensure that the Testing directory is properly cleaned and reset before commit.
|
||||||
- Ensure that the .gitkeep file is placed into Testing/dst
|
- Ensure that the .gitkeep file is placed into Testing/dst
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
|
|
||||||
<Version Condition="'$(RELEASE_VERSION)' != ''">$(RELEASE_VERSION)</Version>
|
<Version Condition="'$(RELEASE_VERSION)' != ''">$(RELEASE_VERSION)</Version>
|
||||||
<VersionPrefix Condition="'$(RELEASE_VERSION)' == ''">0.0.2</VersionPrefix>
|
<VersionPrefix Condition="'$(RELEASE_VERSION)' == ''">0.0.3</VersionPrefix>
|
||||||
<VersionSuffix Condition="'$(RELEASE_VERSION)' == ''">$([System.DateTime]::UtcNow.ToString(`yyyyMMdd-HHmm`))</VersionSuffix>
|
<VersionSuffix Condition="'$(RELEASE_VERSION)' == ''">$([System.DateTime]::UtcNow.ToString(`yyyyMMdd-HHmm`))</VersionSuffix>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user