* Run code cleanup * Start manual cleanup after dotnet format * Finish up manual pass * Fix up missed warnings * Fix after merge * Update src/Umbraco.Core/Cache/ContentTypeCacheRefresher.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/DataTypeCacheRefresher.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/DeepCloneAppCache.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/DomainCacheRefresher.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/MacroCacheRefresher.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/MediaCacheRefresher.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/MemberCacheRefresher.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Cache/MemberGroupCacheRefresher.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Composing/SetCollectionBuilderBase.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/ContentApps/ContentAppFactoryCollectionBuilder.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Dashboards/DashboardCollectionBuilder.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/ContentTypeRefreshedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/ContentTypeSavedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/ContentTypeSavingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/DictionaryCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/DataTypeCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/ContentUnpublishingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/DictionaryItemDeletingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/DictionaryItemSavedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/DictionaryItemSavingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/DomainCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/LanguageCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MacroCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaEmptiedRecycleBinNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaEmptyingRecycleBinNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaMovedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaMovedToRecycleBinNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaMovedToRecycleBinNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaMovingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaMovingToRecycleBinNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaTreeChangeNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaTreeChangeNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaTypeChangedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaTypeDeletingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaTypeMovedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaTypeMovingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaTypeMovingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MediaTypeRefreshedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberGroupCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberGroupDeletingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberGroupSavedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberGroupSavingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberTypeChangedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberTypeDeletedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberTypeDeletingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberTypeMovedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberTypeMovedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberTypeMovingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberTypeMovingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberTypeRefreshedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MemberTypeSavingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/StringExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/UriExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MovedToRecycleBinNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MovedToRecycleBinNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MovingToRecycleBinNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/MovingToRecycleBinNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PartialViewDeletingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Extensions/UriExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/IO/PhysicalFileSystem.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/IO/PhysicalFileSystem.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/IO/ShadowWrapper.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Logging/DisposableTimer.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Install/InstallSteps/UpgradeStep.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Mapping/MapDefinitionCollectionBuilder.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PartialViewSavedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Models/ContentEditing/ContentVariationDisplay.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PartialViewSavingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PublicAccessCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PublicAccessEntryDeletedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PublicAccessEntryDeletingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PublicAccessEntryDeletingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PublicAccessEntrySavedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PublicAccessEntrySavingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/PublicAccessEntrySavingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/RelationTypeCacheRefresherNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/RelationTypeDeletingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/RelationTypeSavedNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/RelationTypeSavingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/StatefulNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/StylesheetDeletingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Notifications/StylesheetSavingNotification.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Models/DeepCloneHelper.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Models/File.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Models/PropertyGroupExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update src/Umbraco.Core/Models/PropertyGroupExtensions.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Fix based on review * Fix after merge Signed-off-by: Zeegaan <nge@umbraco.dk> Co-authored-by: Nikolaj Geisle <niko737@edu.ucl.dk> Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> Co-authored-by: Zeegaan <nge@umbraco.dk>
187 lines
7.0 KiB
C#
187 lines
7.0 KiB
C#
using Microsoft.Extensions.FileProviders;
|
|
using Microsoft.Extensions.Logging;
|
|
using Umbraco.Cms.Core.Hosting;
|
|
using Umbraco.Extensions;
|
|
|
|
namespace Umbraco.Cms.Core.IO;
|
|
|
|
internal class ShadowWrapper : IFileSystem, IFileProviderFactory
|
|
{
|
|
private static readonly string ShadowFsPath = Constants.SystemDirectories.TempData.EnsureEndsWith('/') + "ShadowFs";
|
|
private readonly IHostingEnvironment _hostingEnvironment;
|
|
private readonly IIOHelper _ioHelper;
|
|
|
|
private readonly Func<bool?>? _isScoped;
|
|
private readonly ILoggerFactory _loggerFactory;
|
|
private readonly string _shadowPath;
|
|
private string? _shadowDir;
|
|
private ShadowFileSystem? _shadowFileSystem;
|
|
|
|
public ShadowWrapper(IFileSystem innerFileSystem, IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, ILoggerFactory loggerFactory, string shadowPath, Func<bool?>? isScoped = null)
|
|
{
|
|
InnerFileSystem = innerFileSystem;
|
|
_ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper));
|
|
_hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
|
|
_loggerFactory = loggerFactory;
|
|
_shadowPath = shadowPath;
|
|
_isScoped = isScoped;
|
|
}
|
|
|
|
public IFileSystem InnerFileSystem { get; }
|
|
|
|
public bool CanAddPhysical => FileSystem.CanAddPhysical;
|
|
|
|
private IFileSystem FileSystem
|
|
{
|
|
get
|
|
{
|
|
if (_isScoped is not null && _shadowFileSystem is not null)
|
|
{
|
|
var isScoped = _isScoped!();
|
|
|
|
// if the filesystem is created *after* shadowing starts, it won't be shadowing
|
|
// better not ignore that situation and raised a meaningful (?) exception
|
|
if (isScoped.HasValue && isScoped.Value && _shadowFileSystem == null)
|
|
{
|
|
throw new Exception("The filesystems are shadowing, but this filesystem is not.");
|
|
}
|
|
|
|
return isScoped.HasValue && isScoped.Value
|
|
? _shadowFileSystem
|
|
: InnerFileSystem;
|
|
}
|
|
|
|
return InnerFileSystem;
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public IFileProvider? Create() =>
|
|
InnerFileSystem.TryCreateFileProvider(out IFileProvider? fileProvider) ? fileProvider : null;
|
|
|
|
public IEnumerable<string> GetDirectories(string path) => FileSystem.GetDirectories(path);
|
|
|
|
public void DeleteDirectory(string path) => FileSystem.DeleteDirectory(path);
|
|
|
|
public void DeleteDirectory(string path, bool recursive) => FileSystem.DeleteDirectory(path, recursive);
|
|
|
|
public bool DirectoryExists(string path) => FileSystem.DirectoryExists(path);
|
|
|
|
public void AddFile(string path, Stream stream) => FileSystem.AddFile(path, stream);
|
|
|
|
public void AddFile(string path, Stream stream, bool overrideExisting) =>
|
|
FileSystem.AddFile(path, stream, overrideExisting);
|
|
|
|
public IEnumerable<string> GetFiles(string path) => FileSystem.GetFiles(path);
|
|
|
|
public IEnumerable<string> GetFiles(string path, string filter) => FileSystem.GetFiles(path, filter);
|
|
|
|
public Stream OpenFile(string path) => FileSystem.OpenFile(path);
|
|
|
|
public void DeleteFile(string path) => FileSystem.DeleteFile(path);
|
|
|
|
public bool FileExists(string path) => FileSystem.FileExists(path);
|
|
|
|
public string GetRelativePath(string fullPathOrUrl) => FileSystem.GetRelativePath(fullPathOrUrl);
|
|
|
|
public string GetFullPath(string path) => FileSystem.GetFullPath(path);
|
|
|
|
public string GetUrl(string? path) => FileSystem.GetUrl(path);
|
|
|
|
public DateTimeOffset GetLastModified(string path) => FileSystem.GetLastModified(path);
|
|
|
|
public DateTimeOffset GetCreated(string path) => FileSystem.GetCreated(path);
|
|
|
|
public long GetSize(string path) => FileSystem.GetSize(path);
|
|
|
|
public static string CreateShadowId(IHostingEnvironment hostingEnvironment)
|
|
{
|
|
const int retries = 50; // avoid infinite loop
|
|
const int idLength = 8; // 6 chars
|
|
|
|
// shorten a Guid to idLength chars, and see whether it collides
|
|
// with an existing directory or not - if it does, try again, and
|
|
// we should end up with a unique identifier eventually - but just
|
|
// detect infinite loops (just in case)
|
|
for (var i = 0; i < retries; i++)
|
|
{
|
|
var id = GuidUtils.ToBase32String(Guid.NewGuid(), idLength);
|
|
|
|
var virt = ShadowFsPath + "/" + id;
|
|
var shadowDir = hostingEnvironment.MapPathContentRoot(virt);
|
|
if (Directory.Exists(shadowDir))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Directory.CreateDirectory(shadowDir);
|
|
return id;
|
|
}
|
|
|
|
throw new Exception($"Could not get a shadow identifier (tried {retries} times)");
|
|
}
|
|
|
|
public void AddFile(string path, string physicalPath, bool overrideIfExists = true, bool copy = false) =>
|
|
FileSystem.AddFile(path, physicalPath, overrideIfExists, copy);
|
|
|
|
internal void Shadow(string id)
|
|
{
|
|
// note: no thread-safety here, because ShadowFs is thread-safe due to the check
|
|
// on ShadowFileSystemsScope.None - and if None is false then we should be running
|
|
// in a single thread anyways
|
|
var virt = Path.Combine(ShadowFsPath, id, _shadowPath);
|
|
_shadowDir = _hostingEnvironment.MapPathContentRoot(virt);
|
|
Directory.CreateDirectory(_shadowDir);
|
|
var tempfs = new PhysicalFileSystem(_ioHelper, _hostingEnvironment, _loggerFactory.CreateLogger<PhysicalFileSystem>(), _shadowDir, _hostingEnvironment.ToAbsolute(virt));
|
|
_shadowFileSystem = new ShadowFileSystem(InnerFileSystem, tempfs);
|
|
}
|
|
|
|
internal void UnShadow(bool complete)
|
|
{
|
|
ShadowFileSystem? shadowFileSystem = _shadowFileSystem;
|
|
var dir = _shadowDir;
|
|
_shadowFileSystem = null;
|
|
_shadowDir = null;
|
|
|
|
try
|
|
{
|
|
// this may throw an AggregateException if some of the changes could not be applied
|
|
if (complete)
|
|
{
|
|
shadowFileSystem?.Complete();
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
// in any case, cleanup
|
|
try
|
|
{
|
|
Directory.Delete(dir!, true);
|
|
|
|
// shadowPath make be path/to/dir, remove each
|
|
dir = dir!.Replace('/', Path.DirectorySeparatorChar);
|
|
var min = _hostingEnvironment.MapPathContentRoot(ShadowFsPath).Length;
|
|
var pos = dir.LastIndexOf(Path.DirectorySeparatorChar);
|
|
while (pos > min)
|
|
{
|
|
dir = dir.Substring(0, pos);
|
|
if (Directory.EnumerateFileSystemEntries(dir).Any() == false)
|
|
{
|
|
Directory.Delete(dir, true);
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
|
|
pos = dir.LastIndexOf(Path.DirectorySeparatorChar);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// ugly, isn't it? but if we cannot cleanup, bah, just leave it there
|
|
}
|
|
}
|
|
}
|
|
}
|