X Tutup
The Wayback Machine - https://web.archive.org/web/20220311003207/https://github.com/PowerShell/PowerShell/pull/13622
Skip to content
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

Closed
wants to merge 9 commits into from

Conversation

Joe-Zer0
Copy link

@Joe-Zer0 Joe-Zer0 commented Sep 11, 2020

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

@Joe-Zer0 Joe-Zer0 requested a review from anmenaga as a code owner Sep 11, 2020
@microsoft-cla
Copy link

@microsoft-cla microsoft-cla bot commented Sep 11, 2020

CLA assistant check
All CLA requirements met.

@iSazonov iSazonov requested a review from PaulHigin Sep 12, 2020
@iSazonov
Copy link
Collaborator

@iSazonov iSazonov commented Sep 12, 2020

@Joe-Zer0 Please add in Summary all that is changed in the PR - this helps reviewers.
Also please add a test/tests for local scenario.

@Joe-Zer0
Copy link
Author

@Joe-Zer0 Joe-Zer0 commented Sep 14, 2020

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!

@iSazonov
Copy link
Collaborator

@iSazonov iSazonov commented Sep 15, 2020

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.

@Joe-Zer0
Copy link
Author

@Joe-Zer0 Joe-Zer0 commented Sep 15, 2020

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.

@Joe-Zer0
Copy link
Author

@Joe-Zer0 Joe-Zer0 commented Sep 18, 2020

Please let me know if there is anything else I need to be doing. Thanks!

@Joe-Zer0
Copy link
Author

@Joe-Zer0 Joe-Zer0 commented Sep 21, 2020

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?

@iSazonov
Copy link
Collaborator

@iSazonov iSazonov commented Sep 23, 2020

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 123 a coder reader doesn't understand what is 123. It is better to define a named const and use it:

    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.

@Joe-Zer0
Copy link
Author

@Joe-Zer0 Joe-Zer0 commented Sep 28, 2020

Please let me know what else needs to be done for this PR. Thanks!

Copy link
Collaborator

@PaulHigin PaulHigin left a comment

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,
Copy link
Collaborator

@PaulHigin PaulHigin Sep 28, 2020

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.

Copy link
Member

@JamesWTruher JamesWTruher Sep 30, 2020

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,
Copy link
Collaborator

@PaulHigin PaulHigin Sep 28, 2020

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(','))
Copy link
Collaborator

@PaulHigin PaulHigin Sep 28, 2020

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());
Copy link
Collaborator

@PaulHigin PaulHigin Sep 28, 2020

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());
Copy link
Collaborator

@PaulHigin PaulHigin Sep 28, 2020

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
Copy link
Collaborator

@PaulHigin PaulHigin Sep 28, 2020

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?

Copy link
Author

@Joe-Zer0 Joe-Zer0 Oct 5, 2020

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.

@Joe-Zer0
Copy link
Author

@Joe-Zer0 Joe-Zer0 commented Oct 5, 2020

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!

Copy link
Collaborator

@PaulHigin PaulHigin left a comment

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.

@iSazonov
Copy link
Collaborator

@iSazonov iSazonov commented Oct 8, 2020

@Joe-Zer0 Please make the feature experimental. You can find examples by "ExperimentalFeature" keyword in the repo.
In short:

  • add new feature in static ExperimentalFeature()
  • wrap new code with if (ExperimentalFeature.IsEnable("feature name"))
  • skip new tests if the new feature is disabled.

@Joe-Zer0
Copy link
Author

@Joe-Zer0 Joe-Zer0 commented Oct 13, 2020

What are next steps?

@iSazonov
Copy link
Collaborator

@iSazonov iSazonov commented Oct 14, 2020

What are next steps?

Waiting @daxian-dbw ...

@msftbot
Copy link

@msftbot msftbot bot commented Oct 21, 2020

This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days.
Maintainer, please provide feedback and/or mark it as Waiting on Author

@Joe-Zer0
Copy link
Author

@Joe-Zer0 Joe-Zer0 commented Nov 9, 2020

Is there any update on this?

@iSazonov
Copy link
Collaborator

@iSazonov iSazonov commented Nov 10, 2020

I hope MSFT team will review community PRs after PowerShell 7.1 release in weeks.

@msftbot
Copy link

@msftbot msftbot bot commented Nov 17, 2020

This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days.
Maintainer, please provide feedback and/or mark it as Waiting on Author

Copy link
Member

@daxian-dbw daxian-dbw left a comment

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;
}
Copy link
Member

@daxian-dbw daxian-dbw Nov 1, 2021

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

Suggested change
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);
Copy link
Member

@daxian-dbw daxian-dbw Nov 1, 2021

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;
}
Copy link
Member

@daxian-dbw daxian-dbw Nov 1, 2021

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.

Suggested change
if (ExperimentalFeature.IsEnabled("PSCopyItemDirectoryAttributes")) {
destDir.Attributes = sourceDirectoryAttributes;
}
if (ExperimentalFeature.IsEnabled("PSCopyItemDirectoryAttributes"))
{
destDir.Attributes = sourceDirectoryAttributes;
}

[System.IO.FileAttributes] $attributes,
Copy link
Member

@daxian-dbw daxian-dbw Nov 1, 2021

Choose a reason for hiding this comment

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

Suggested change
[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 {{
Copy link
Member

@daxian-dbw daxian-dbw Nov 1, 2021

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 {{
Copy link
Member

@daxian-dbw daxian-dbw Nov 1, 2021

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
}}
Copy link
Member

@daxian-dbw daxian-dbw Nov 1, 2021

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
}}
Copy link
Member

@daxian-dbw daxian-dbw Nov 1, 2021

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);
Copy link
Member

@daxian-dbw daxian-dbw Nov 1, 2021

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)]
Copy link
Member

@daxian-dbw daxian-dbw Nov 1, 2021

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.

@msftbot
Copy link

@msftbot msftbot bot commented Nov 26, 2021

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.

@msftbot msftbot bot closed this Dec 7, 2021
@iSazonov iSazonov reopened this Dec 7, 2021
@pull-request-quantifier
Copy link

@pull-request-quantifier pull-request-quantifier bot commented Dec 7, 2021

This PR has 106 quantified lines of changes. In general, a change size of upto 200 lines is ideal for the best PR experience!


Quantification details

Label      : Medium
Size       : +74 -32
Percentile : 41.2%

Total files changed: 3

Change summary by file extension:
.cs : +50 -32
.ps1 : +24 -0

Change counts above are quantified counts, based on the PullRequestQuantifier customizations.

Why proper sizing of changes matters

Optimal pull request sizes drive a better predictable PR flow as they strike a
balance between between PR complexity and PR review overhead. PRs within the
optimal size (typical small, or medium sized PRs) mean:

  • Fast and predictable releases to production:
    • Optimal size changes are more likely to be reviewed faster with fewer
      iterations.
    • Similarity in low PR complexity drives similar review times.
  • Review quality is likely higher as complexity is lower:
    • Bugs are more likely to be detected.
    • Code inconsistencies are more likely to be detetcted.
  • Knowledge sharing is improved within the participants:
    • Small portions can be assimilated better.
  • Better engineering practices are exercised:
    • Solving big problems by dividing them in well contained, smaller problems.
    • Exercising separation of concerns within the code changes.

What can I do to optimize my changes

  • Use the PullRequestQuantifier to quantify your PR accurately
    • Create a context profile for your repo using the context generator
    • Exclude files that are not necessary to be reviewed or do not increase the review complexity. Example: Autogenerated code, docs, project IDE setting files, binaries, etc. Check out the Excluded section from your prquantifier.yaml context profile.
    • Understand your typical change complexity, drive towards the desired complexity by adjusting the label mapping in your prquantifier.yaml context profile.
    • Only use the labels that matter to you, see context specification to customize your prquantifier.yaml context profile.
  • Change your engineering behaviors
    • For PRs that fall outside of the desired spectrum, review the details and check if:
      • Your PR could be split in smaller, self-contained PRs instead
      • Your PR only solves one particular issue. (For example, don't refactor and code new features in the same PR).

How to interpret the change counts in git diff output

  • One line was added: +1 -0
  • One line was deleted: +0 -1
  • One line was modified: +1 -1 (git diff doesn't know about modified, it will
    interpret that line like one addition plus one deletion)
  • Change percentiles: Change characteristics (addition, deletion, modification)
    of this PR in relation to all other PRs within the repository.


Was this comment helpful? 👍  👌  👎 (Email)
Customize PullRequestQuantifier for this repository.

@msftbot msftbot bot removed the Stale label Dec 7, 2021
@daxian-dbw
Copy link
Member

@daxian-dbw daxian-dbw commented Dec 7, 2021

@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.

@daxian-dbw daxian-dbw closed this Dec 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

5 participants
X Tutup