-
-
Notifications
You must be signed in to change notification settings - Fork 104
Improve windows symlink handling #715
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This pull request modernizes the symbolic link handling implementation by removing the dependency on NCode.ReparsePoints and implementing native Windows symlink functionality. The changes consolidate symlink operations into platform-specific implementations while maintaining compatibility across multiple .NET versions.
Key changes:
- Replaces NCode.ReparsePoints dependency with native Windows P/Invoke implementation
- Consolidates file and directory symlink creation into a unified method
- Adds comprehensive test coverage for various symlink scenarios and edge cases
Reviewed Changes
Copilot reviewed 4 out of 16 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| test/Velopack.Tests/SymbolicLinkTests.cs | Adds extensive test coverage for symlink operations, error handling, and cross-platform compatibility |
| src/lib-csharp/Util/SymbolicLink.cs | Refactors main symlink logic to use unified creation method and removes NCode dependency |
| src/lib-csharp/Util/SymbolicLink.Windows.cs | Implements native Windows symlink operations using P/Invoke with reparse point handling |
| src/lib-csharp/Util/SymbolicLink.Unix.cs | Extracts Unix-specific symlink operations with EINTR signal handling |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.
| } | ||
|
|
||
| [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] | ||
| static extern bool CreateHardLink(string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes); |
Copilot
AI
Aug 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The P/Invoke declaration for CreateHardLink should be moved to a separate platform-specific file or at least grouped with other Windows-specific code, rather than being embedded in the test class.
| static extern bool CreateHardLink(string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes); | |
| // Windows-specific interop methods | |
| internal static class WindowsInterop | |
| { | |
| [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] | |
| public static extern bool CreateHardLink(string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes); | |
| } |
| { | ||
| if (!PInvokeWindowsCreateSymlink(linkPath, target, mode)) { | ||
| var errorCode = Marshal.GetLastWin32Error(); | ||
| throw new InvalidOperationException($"Error creating symlink: {errorCode}", new Win32Exception()); |
Copilot
AI
Aug 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message includes the error code but doesn't include the actual Win32Exception message. Consider using new Win32Exception(errorCode) to get the descriptive error message, or include both the code and description in the message.
| throw new InvalidOperationException($"Error creating symlink: {errorCode}", new Win32Exception()); | |
| var win32Ex = new Win32Exception(errorCode); | |
| throw new InvalidOperationException($"Error creating symlink: {errorCode} - {win32Ex.Message}", win32Ex); |
No description provided.