Correctly copy directory hierarchy

This commit is contained in:
Simon Lübeß
2025-06-26 12:55:55 +02:00
parent 108e24eb38
commit 50bcfa2caf
@@ -13,7 +13,7 @@ class CopyBackgroundTask : BackgroundTask
private int _totalEntriesToCopy; private int _totalEntriesToCopy;
private append Queue<CopyInfo> _pathsToCopy = .() ~ ClearAndDeleteItems!(_); private append Queue<CopyInfo> _pathsToCopy = .() ~ ClearAndDeleteItems!(_);
private append Queue<String> _scanQueue = .() ~ ClearAndDeleteItems!(_); private append Queue<CopyInfo> _scanQueue = .() ~ ClearAndDeleteItems!(_);
private enum OverwriteMode private enum OverwriteMode
{ {
@@ -31,19 +31,17 @@ class CopyBackgroundTask : BackgroundTask
private class CopyInfo private class CopyInfo
{ {
public String SourcePath ~ delete:append _; public append String SourcePath = .();
public String TargetPath ~ delete:append _; // If this entry is actually inside a directory we copy, this contains the path of this entry inside this directory.
public append String SubPath = .();
public append String TargetPath = .();
public OverwriteMode OverwriteMode; public OverwriteMode OverwriteMode;
[AllowAppend] [AllowAppend]
public this(StringView sourcePath, StringView targetPath, OverwriteMode overwriteMode) public this(StringView sourcePath, StringView targetPath, OverwriteMode overwriteMode)
{ {
String src = append String(sourcePath); SourcePath.Set(sourcePath);
String tgt = append String(targetPath); TargetPath.Set(targetPath);
SourcePath = src;
TargetPath = tgt;
OverwriteMode = overwriteMode; OverwriteMode = overwriteMode;
} }
} }
@@ -62,7 +60,7 @@ class CopyBackgroundTask : BackgroundTask
for (String path in sourcePaths) for (String path in sourcePaths)
{ {
_sourcePath.Add(new String(path)); _sourcePath.Add(new String(path));
_scanQueue.Add(new String(path)); _scanQueue.Add(new CopyInfo(path, "", .None));
} }
_totalEntriesToCopy = sourcePaths.Count; _totalEntriesToCopy = sourcePaths.Count;
@@ -94,38 +92,58 @@ class CopyBackgroundTask : BackgroundTask
private Result<void, CopyError> CollectFilesToCopy() private Result<void, CopyError> CollectFilesToCopy()
{ {
void RemoveFront() CopyInfo currentEntry = null;
defer
{ {
String path = _scanQueue.PopFront(); if (currentEntry != null && @return case .Err)
delete path; {
_scanQueue.AddFront(currentEntry);
}
} }
while (!_scanQueue.IsEmpty && Running) while (!_scanQueue.IsEmpty && Running)
{ {
//Thread.Sleep(1000); //Thread.Sleep(1000);
String currentPath = _scanQueue.Peek(); currentEntry = _scanQueue.PopFront();
//FileInfo sourceInfo = scope FileInfo(currentPath); let sourcePath = (StringView)currentEntry.SourcePath;
String fileName = scope .(); let fileName = scope String();
Path.GetFileName(currentPath, fileName); Path.GetFileName(sourcePath, fileName);
String targetPath = scope .(); let targetPath = scope String();
Path.Combine(targetPath, _targetDirectoryPath, fileName); Path.Combine(targetPath, _targetDirectoryPath, currentEntry.SubPath, fileName);
//FileInfo targetInfo = scope FileInfo(targetPath); if (Directory.Exists(sourcePath))
if (Directory.Exists(currentPath))
{ {
/*for (FileFindEntry e in Directory.Enumerate(currentPath)) if (Directory.Exists(targetPath))
{ {
String entryPath = new String(); switch (CurrentFileMode)
e.GetFilePath(entryPath); {
_scanQueue.Add(entryPath); case .KeepBoth, .CombineDirectories, .Skip:
}*/ default:
return .Err(.TargetDirectoryExists(new String(fileName)));
} }
else if (File.Exists(currentPath)) }
if (!CurrentFileMode.HasFlag(.Skip))
{
_pathsToCopy.Add(currentEntry);
currentEntry.OverwriteMode = CurrentFileMode;
for (FileFindEntry e in Directory.Enumerate(currentEntry.SourcePath))
{
let entryPath = scope String();
e.GetFilePath(entryPath);
let newEntry = new CopyInfo(entryPath, "", .None);
_scanQueue.Add(newEntry);
Path.Combine(newEntry.SubPath, currentEntry.SubPath, fileName);
}
}
_nextFileMode = .None;
}
else if (File.Exists(sourcePath))
{ {
if (File.Exists(targetPath)) if (File.Exists(targetPath))
{ {
@@ -137,8 +155,11 @@ class CopyBackgroundTask : BackgroundTask
} }
} }
_pathsToCopy.Add(new CopyInfo(currentPath, targetPath, CurrentFileMode)); if (!CurrentFileMode.HasFlag(.Skip))
RemoveFront(); {
_pathsToCopy.Add(currentEntry);
currentEntry.OverwriteMode = CurrentFileMode;
}
_nextFileMode = .None; _nextFileMode = .None;
} }
} }
@@ -175,35 +196,52 @@ class CopyBackgroundTask : BackgroundTask
return .Finished; return .Finished;
} }
private Result<void> CopyPath(CopyInfo sourcePath) private Result<void> CopyPath(CopyInfo copyInfo)
{ {
if (Directory.Exists(sourcePath.SourcePath)) if (Directory.Exists(copyInfo.SourcePath))
{ {
//bool forceOverwrite = false;
if (Directory.Exists(copyInfo.TargetPath))
{
switch (CurrentFileMode)
{
case .KeepBoth:
String fileName = scope .();
Path.GetFileName(copyInfo.SourcePath, fileName);
Path.FindFreePath(_targetDirectoryPath, fileName, "", copyInfo.TargetPath..Clear());
case .CombineDirectories:
return .Ok;
default:
return .Err;//(.TargetDirectoryExists);
} }
else if (File.Exists(sourcePath.SourcePath)) }
Directory.CreateDirectory(copyInfo.TargetPath);
}
else if (File.Exists(copyInfo.SourcePath))
{ {
bool forceOverwrite = false; bool forceOverwrite = false;
if (File.Exists(sourcePath.TargetPath)) if (File.Exists(copyInfo.TargetPath))
{ {
switch (sourcePath.OverwriteMode) switch (copyInfo.OverwriteMode)
{ {
case .KeepBoth: case .KeepBoth:
String fileExtension = scope .(); String fileExtension = scope .();
Path.GetExtension(sourcePath.TargetPath, fileExtension); Path.GetExtension(copyInfo.TargetPath, fileExtension);
String fileName = scope .(); String fileName = scope .();
Path.GetFileName(sourcePath.SourcePath, fileName); Path.GetFileName(copyInfo.SourcePath, fileName);
Path.FindFreePath(_targetDirectoryPath, fileName.Substring(0..<^fileExtension.Length), fileExtension, sourcePath.TargetPath..Clear()); Path.FindFreePath(_targetDirectoryPath, fileName.Substring(0..<^fileExtension.Length), fileExtension, copyInfo.TargetPath..Clear());
case .OverwriteFile: case .OverwriteFile:
forceOverwrite = true; forceOverwrite = true;
case .Skip:
default: default:
return .Err;//(.TargetFileExists); return .Err;//(.TargetFileExists);
} }
} }
File.Copy(sourcePath.SourcePath, sourcePath.TargetPath, forceOverwrite); File.Copy(copyInfo.SourcePath, copyInfo.TargetPath, forceOverwrite);
} }
else else
{ {