@@ -29,9 +29,7 @@ public async Task<Result<Unit, ResultErrors>> Generate(string sourcePath, string
2929 return Result . Error ( "Output path cannot be a system directory." ) ;
3030 }
3131
32- if ( ! Directory . Exists ( outputPath ) ) {
33- Directory . CreateDirectory ( outputPath ) ;
34- }
32+ Directory . CreateDirectory ( outputPath ) ;
3533
3634 // load page files
3735 var pageFiles = pageFileLoader . LoadFiles ( ) ;
@@ -40,19 +38,61 @@ public async Task<Result<Unit, ResultErrors>> Generate(string sourcePath, string
4038 return Result . Error ( $ "No page files found in the source directory '{ sourcePath } '.") ;
4139 }
4240
41+ var continuationErrors = new ResultErrors ( ) ;
42+
43+ // delete any index.html files that aren't in the source
44+ var pageOutputPathIndex =
45+ new HashSet < string > (
46+ pageFiles . Select ( x => x . OutputPath ) ,
47+ StringComparer . OrdinalIgnoreCase ) ;
48+
49+ var filesToDelete = new List < string > ( ) ;
50+
51+ foreach ( var file in Directory . EnumerateFiles ( outputPath , "index.html" , SearchOption . AllDirectories ) ) {
52+ var fullPath = Path . GetFullPath ( file ) ;
53+ if ( ! pageOutputPathIndex . Contains ( fullPath ) ) {
54+ filesToDelete . Add ( fullPath ) ;
55+ }
56+ }
57+
58+ Parallel . ForEach ( filesToDelete , file => {
59+ try {
60+ File . Delete ( file ) ;
61+ }
62+ catch ( Exception ex ) {
63+ continuationErrors . Add ( Path . GetRelativePath ( sourcePath , file ) , $ "Failed to delete file '{ file } ': { ex . Message } ") ;
64+ }
65+ } ) ;
66+
67+ // delete any empty directories
68+ var directoriesToDelete = new List < string > ( ) ;
69+ foreach ( var dir in Directory . GetDirectories ( outputPath , "*" , SearchOption . AllDirectories ) . OrderByDescending ( x => x . Length ) ) {
70+ if ( ! Directory . EnumerateFileSystemEntries ( dir ) . Any ( ) ) {
71+ directoriesToDelete . Add ( dir ) ;
72+ }
73+ }
74+
75+ Parallel . ForEach ( directoriesToDelete , x => {
76+ try {
77+ Directory . Delete ( x ) ;
78+ }
79+ catch ( Exception ex ) {
80+ continuationErrors . Add ( Path . GetRelativePath ( sourcePath , x ) , $ "Failed to delete directory '{ x } ': { ex . Message } ") ;
81+ }
82+ } ) ;
83+
4384 // parse pages
4485 var pageTasks = pageFiles . Select ( async pageFile => {
4586 using var input = new StreamReader ( pageFile . InputPath ) ;
4687 // using var stream = new FileStream(pageFile.InputPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite & FileShare.Delete);
4788 // using var input = new StreamReader(stream);
48- var page = await pageParser . Parse ( input , pageFile ) ;
89+ var page = await pageParser . Parse ( input , pageFile ) . ConfigureAwait ( false ) ;
4990 return ( page , pageFile . InputPath , pageFile . OutputPath ) ;
5091 } ) ;
5192
5293 var pageResults = await Task . WhenAll ( pageTasks ) ;
5394
5495 var pages = new List < ( Page page , string outputPath ) > ( ) ;
55- var continuationErrors = new ResultErrors ( ) ;
5696
5797 foreach ( var ( page , inputPath , pageOutputPath ) in pageResults ) {
5898 if ( page . TryGet ( out var p ) ) {
@@ -65,39 +105,19 @@ public async Task<Result<Unit, ResultErrors>> Generate(string sourcePath, string
65105
66106 var pageCollections = PageCollectionFactory . Create ( pages . Select ( x => x . page ) ) ;
67107
68- // delete any index.html files that aren't in the source
69- var pageOutputPathIndex =
70- new HashSet < string > (
71- pageFiles . Select ( x => x . OutputPath ) ,
72- StringComparer . OrdinalIgnoreCase ) ;
73-
74- foreach ( var file in Directory . EnumerateFiles ( outputPath , "index.html" , SearchOption . AllDirectories ) ) {
75- var fullPath = Path . GetFullPath ( file ) ;
76- if ( ! pageOutputPathIndex . Contains ( fullPath ) ) {
77- File . Delete ( fullPath ) ;
78- }
79- }
80-
81- // delete any empty directories
82- foreach ( var dir in Directory . GetDirectories ( outputPath , "*" , SearchOption . AllDirectories ) . OrderByDescending ( x => x . Length ) ) {
83- if ( ! Directory . EnumerateFileSystemEntries ( dir ) . Any ( ) ) {
84- Directory . Delete ( dir , false ) ;
85- }
86- }
87-
88108 // render pages
89109 var pageRenderTasks = pages . Select ( async pageTuple => {
90110 var ( page , outputPath ) = pageTuple ;
91111 var outputDir = Path . GetDirectoryName ( outputPath ) ;
92112
93- if ( outputDir is not null && ! Directory . Exists ( outputDir ) ) {
113+ if ( outputDir is not null ) {
94114 Directory . CreateDirectory ( outputDir ) ;
95115 }
96116
97117 var renderedContent = await viewEngine . Render (
98118 page : page ,
99119 siteConfig : siteConfig ,
100- collections : pageCollections ) ;
120+ collections : pageCollections ) . ConfigureAwait ( false ) ;
101121
102122 using var writer = new StreamWriter ( outputPath ) ;
103123 await writer . WriteAsync ( renderedContent ) ;
0 commit comments