Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 32 additions & 6 deletions src/Runner.Sdk/Util/IOUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -389,23 +389,49 @@ public static void CopyDirectory(string source, string target, CancellationToken
ArgUtil.NotNull(cancellationToken, nameof(cancellationToken));
cancellationToken.ThrowIfCancellationRequested();

// Get the file contents of the directory to copy.
DirectoryInfo sourceDir = new(source);

if (sourceDir.Attributes.HasFlag(FileAttributes.ReparsePoint))
{
DirectoryInfo targetDir = new(target);

if (targetDir.Exists &&
targetDir.Attributes.HasFlag(FileAttributes.ReparsePoint) &&
targetDir.LinkTarget.Equals(sourceDir.LinkTarget, StringComparison.OrdinalIgnoreCase))
{
return;
}

Directory.CreateSymbolicLink(target, sourceDir.LinkTarget);
return;
}

// Create the target directory.
Directory.CreateDirectory(target);

// Get the file contents of the directory to copy.
DirectoryInfo sourceDir = new(source);
foreach (FileInfo sourceFile in sourceDir.GetFiles() ?? new FileInfo[0])
{
// Check if the file already exists.
cancellationToken.ThrowIfCancellationRequested();

// Check if the file already exists.
FileInfo targetFile = new(Path.Combine(target, sourceFile.Name));
if (!targetFile.Exists ||
sourceFile.Length != targetFile.Length ||
sourceFile.LastWriteTime != targetFile.LastWriteTime)
if (targetFile.Exists &&
sourceFile.Length == targetFile.Length &&
sourceFile.LastWriteTime == targetFile.LastWriteTime)
{
continue;
}

// Check if source is a symlink
if (!sourceFile.Attributes.HasFlag(FileAttributes.ReparsePoint))
Copy link

Copilot AI Jun 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] For file symlinks, add a check to skip recreating an existing link when the target matches, similar to the directory case, to avoid unnecessary filesystem operations.

Copilot uses AI. Check for mistakes.
Copy link
Author

@black-desk black-desk Jun 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this logic may have been covered by the section above that checks for the existence of target

{
// Copy the file.
sourceFile.CopyTo(targetFile.FullName, true);
continue;
}

File.CreateSymbolicLink(targetFile.FullName, sourceFile.LinkTarget);
}

// Copy the subdirectories.
Expand Down