PowerShell / PowerShell Public
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
Update Copy-Item to copy directory attributes #13622
Conversation
|
@Joe-Zer0 Please add in Summary all that is changed in the PR - this helps reviewers. |
|
I added a unit test. But I made a mess of the commit's. I am new to rebaseing. I was attempting to add this change to the existing commit. I believe that is the desired action for this repository. I would appreciate a point in the right direction to clean them up. Thanks! |
You have no need to rebase until maintainers ask you. You should add new commits. To clean you should revert the rebase. If you can not do this you can close the PR and restart with new branch and PR. |
|
I have fix the git commit's to show 2 commit's: the original, and the addition of the unit test. I have also updated the summary to mention the 3 different scenarios that were updated by the changes. |
test/powershell/Modules/Microsoft.PowerShell.Management/Copy-Item.Tests.ps1
Outdated
Show resolved
Hide resolved
|
Please let me know if there is anything else I need to be doing. Thanks! |
src/System.Management.Automation/namespaces/FileSystemProvider.cs
Outdated
Show resolved
Hide resolved
src/System.Management.Automation/namespaces/FileSystemProvider.cs
Outdated
Show resolved
Hide resolved
src/System.Management.Automation/namespaces/FileSystemProvider.cs
Outdated
Show resolved
Hide resolved
src/System.Management.Automation/namespaces/FileSystemProvider.cs
Outdated
Show resolved
Hide resolved
test/powershell/Modules/Microsoft.PowerShell.Management/Copy-Item.Tests.ps1
Outdated
Show resolved
Hide resolved
|
I have made the requested changes. I was able to add a test for copying TO and FROM a remote session. To help me learn, can you explain why you wanted one parameter as a named parameter, but not the other one? |
Common practice in C# use self-descriptive names everywhere. If you use a constant like const int DefaultDelay = 123;
stopTime = startTime + DefaultDelay;If we say about constants in arguments it is better to use names too as named arguments: Create(Capacity: 100);So we get more readable code. |
|
Please let me know what else needs to be done for this PR. Thanks! |
Added some comments, but my concern is if this new behavior might be a breaking change. Are there scenarios where setting directory attributes can fail?
| @@ -3730,6 +3732,7 @@ private void CopyItemFromRemoteSession(string path, string destinationPath, bool | |||
| destinationPath, | |||
| force, | |||
| recurse, | |||
| ItemInfo, | |||
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.
We should pass in either the ItemInfo hash table itself or properties within the ItemInfo here, but not both.
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.
yah, i'm also concerned that we're converting the attributes to strings and then back to attributes
| @@ -4048,6 +4052,7 @@ private void CopyFileInfoItem(FileInfo file, string destinationPath, bool force, | |||
| string destination, | |||
| bool force, | |||
| bool recurse, | |||
| Hashtable srcDir, | |||
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.
Should be named 'srcDirInfo', or just pass in attributes (see above comment).
| @@ -4067,7 +4072,9 @@ private void CopyFileInfoItem(FileInfo file, string destinationPath, bool force, | |||
| { | |||
| // Create destinationPath directory. This will fail if the directory already exists | |||
| // and Force is not selected. | |||
| CreateDirectory(destination, false); | |||
| var destDir = CreateDirectory(destination, streamOutput: true); | |||
| foreach(var attribute in ((string)srcDir["Attributes"]).Split(',')) | |||
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.
Error handling? Probably should use 'TryParse' here.
| CreateDirectory(destination, false); | ||
| var destDir = CreateDirectory(destination, streamOutput: true); | ||
| foreach(var attribute in ((string)srcDir["Attributes"]).Split(',')) | ||
| destDir.Attributes |= Enum.Parse<System.IO.FileAttributes>(attribute.Trim()); |
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.
Please add comment to clarify that this applies the attribute immediately to the newly created directory.
| CreateDirectory(destination, false); | ||
| var destDir = CreateDirectory(destination, streamOutput: true); | ||
| foreach(var attribute in ((string)srcDir["Attributes"]).Split(',')) | ||
| destDir.Attributes |= Enum.Parse<System.IO.FileAttributes>(attribute.Trim()); |
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.
Error handling? Can this fail?
| @@ -9210,6 +9224,7 @@ function PSCreateDirectoryOnRemoteSession | |||
| if ($force) | |||
| {{ | |||
| Microsoft.PowerShell.Management\New-Item $createDirectoryPath -ItemType Directory -Force | Out-Null | |||
| (Get-Item $createDirectoryPath -Force).Attributes = $attributes | |||
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.
If dir path already exists, should new attributes be checked and applied?
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.
I believe the intent of the Force flag is to complete the copy operation regardless of initial state. So the new attributes should be applied.
|
When copying an item from a session, I am no longer converting FileAttributes to a string. I was unable to pass FileAttributes through in the hashtable, I kept receiving "Copy-Item: Unable to cast object of type 'System.Management.Automation.PSObject' to type 'System.IO.FileAttributes'.". I was able to pass it through as byte however. This removes the string manipulation that was the concern for several of the comments. I also updated the parameters for CopyDirectoryFromRemoteSession to pass through the Hashtable. Please let me know what other changes need to be made. Thanks! |
src/System.Management.Automation/namespaces/FileSystemProvider.cs
Outdated
Show resolved
Hide resolved
src/System.Management.Automation/namespaces/FileSystemProvider.cs
Outdated
Show resolved
Hide resolved
Overall LGTM. I am still not sure how setting directory attributes can fail, and if it does whether that should be a terminating or non-terminating error. But since the committee is Ok with this going in to next preview version as 'experimental', I think it is Ok as is and we can change if needed.
|
@Joe-Zer0 Please make the feature experimental. You can find examples by "ExperimentalFeature" keyword in the repo.
|
test/powershell/Modules/Microsoft.PowerShell.Management/Copy-Item.Tests.ps1
Outdated
Show resolved
Hide resolved
|
What are next steps? |
Waiting @daxian-dbw ... |
|
This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days. |
|
Is there any update on this? |
|
I hope MSFT team will review community PRs after PowerShell 7.1 release in weeks. |
|
This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days. |
The remote side could be an older version of PowerShell, so checking ExperimentalFeature.IsEnabled(...) on the remote side won't work.
| if (ExperimentalFeature.IsEnabled("PSCopyItemDirectoryAttributes")) { | ||
| destDir.Attributes = directory.Attributes; | ||
| } |
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.
Please follow the existing formatting in this file
| if (ExperimentalFeature.IsEnabled("PSCopyItemDirectoryAttributes")) { | |
| destDir.Attributes = directory.Attributes; | |
| } | |
| if (ExperimentalFeature.IsEnabled("PSCopyItemDirectoryAttributes")) | |
| { | |
| destDir.Attributes = directory.Attributes; | |
| } |
| CreateDirectory(destination, false); | ||
| // Create destinationPath directory and apply attributes of source directory. | ||
| // This will fail if the directory already exists and Force is not selected. | ||
| var destDir = CreateDirectory(destination, streamOutput: true); |
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.
It was CreateDirectory(destination, false) before the change. Why did you change to true?
| if (ExperimentalFeature.IsEnabled("PSCopyItemDirectoryAttributes")) { | ||
| destDir.Attributes = sourceDirectoryAttributes; | ||
| } |
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.
Same here, please follow the existing formatting in this file.
| if (ExperimentalFeature.IsEnabled("PSCopyItemDirectoryAttributes")) { | |
| destDir.Attributes = sourceDirectoryAttributes; | |
| } | |
| if (ExperimentalFeature.IsEnabled("PSCopyItemDirectoryAttributes")) | |
| { | |
| destDir.Attributes = sourceDirectoryAttributes; | |
| } |
| [System.IO.FileAttributes] $attributes, |
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.
| [System.IO.FileAttributes] $attributes, | |
| [System.IO.FileAttributes] $attributes, |
| @@ -9649,11 +9670,12 @@ function PSGetPathItems | |||
| return $op | |||
| }} | |||
| $items = @(Microsoft.PowerShell.Management\Get-Item -Path $getPathItems | Microsoft.PowerShell.Core\ForEach-Object {{ | |||
| $items = @(Microsoft.PowerShell.Management\Get-Item -Path $getPathItems -Force | Microsoft.PowerShell.Core\ForEach-Object {{ | |||
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.
Why is -Force added?
| }} | ||
| }}) | ||
| $directories = @(Microsoft.PowerShell.Management\Get-ChildItem -Path $getPathDir -Directory | Microsoft.PowerShell.Core\ForEach-Object {{ | ||
| $directories = @(Microsoft.PowerShell.Management\Get-ChildItem -Path $getPathDir -Directory -Force | Microsoft.PowerShell.Core\ForEach-Object {{ |
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.
ditto, why is -Force added?
| if (ExperimentalFeature.IsEnabled('PSCopyItemDirectoryAttributes')) | ||
| {{ | ||
| (Get-Item $createDirectoryPath -Force).Attributes = $attributes | ||
| }} |
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.
When the remote session is an older version of PowerShell, ExperimentalFeature.IsEnabled(PSCopyItemDirectoryAttributes) won't work. I think you will have to decide whether to set the attribute depending on if $attribute is null or not-null. Currently $attributes is of a enum type, so I guess you cannot just pass in null when the feature is disabled.
| if (ExperimentalFeature.IsEnabled('PSCopyItemDirectoryAttributes')) | ||
| {{ | ||
| (Get-Item $createDirectoryPath -Force).Attributes = $attributes | ||
| }} |
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.
Same here, when the remote side is an older version of PS, ExperimentalFeature.IsEnabled('PSCopyItemDirectoryAttributes') won't work.
| { | ||
| ps.AddCommand(CopyFileRemoteUtils.PSCopyToSessionHelperName); | ||
| ps.AddParameter("createDirectoryPath", destination); | ||
| ps.AddParameter("attributes", sourceDirectory.Attributes); |
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.
To put this feature under experimental, you will have to guard this line in a if (ExperimentalFeature.IsEnabled(....)).
| @@ -8886,6 +8894,10 @@ internal static class CopyFileRemoteUtils | |||
| [string] $createDirectoryPath, | |||
| [Parameter(ParameterSetName=""PSCreateDirectoryOnRemoteSession"", Mandatory=$true)] | |||
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.
To make the feature experimental, you will need to decide whether to pass in -Attributes based on if the experimental feature is turned on, so this cannot be Mandatory.
|
This pull request has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 15 days. It will be closed if no further activity occurs within 10 days of this comment. |
|
This PR has Quantification details
Why proper sizing of changes matters
Optimal pull request sizes drive a better predictable PR flow as they strike a
What can I do to optimize my changes
How to interpret the change counts in git diff output
Was this comment helpful? |
|
@iSazonov Please don't open this PR. It's been marked as "Waiting on Author" for 25 days, and the author didn't get to it. So, the bot closed it as part of the housekeeping. The author can re-open when ready to work on it again. |


PR Summary
This change updates Copy-Item to also copy Directory attributes. There are changes to 3 distinct scenarios. Copying a folder locally, copying a folder to a remote session, and copying a folder from a remote session.
PR Context
#13552
PR Checklist
.h,.cpp,.cs,.ps1and.psm1files have the correct copyright headerWIP:or[ WIP ]to the beginning of the title (theWIPbot will keep its status check atPendingwhile the prefix is present) and remove the prefix when the PR is ready.