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

Enable New-Item creates symlinks to non-existent targets #13082

Closed
wants to merge 14 commits into from

Conversation

iSazonov
Copy link
Collaborator

@iSazonov iSazonov commented Jul 2, 2020

PR Summary

Fix #9067.
Fix #13064.
Fix #13136.

  1. Ignore exception if target path can not be resolved (is not exist) and consider it as literal (only first slash is normalized).
  2. Create symlink in the case only if -Force switch presents.

PR Context

PR Checklist

@iSazonov iSazonov added the CL-General Indicates that a PR should be marked as a general cmdlet change in the Change Log label Jul 2, 2020
@ghost ghost assigned anmenaga Jul 2, 2020
@iSazonov
Copy link
Collaborator Author

iSazonov commented Jul 2, 2020

@mklement0 Could you please review and try this? I hope this address your requests.

@iSazonov iSazonov added the Documentation Needed in this repo Documentation is needed in this repo label Jul 2, 2020
@iSazonov iSazonov marked this pull request as ready for review July 3, 2020 09:26
@iSazonov iSazonov requested a review from anmenaga as a code owner July 3, 2020 09:26
if (WildcardPattern.ContainsWildcardCharacters(targetPath))
// If the original target was a relative path, we want to leave it as relative if it did not require
// globbing to resolve.
if (WildcardPattern.ContainsWildcardCharacters(targetPath))
Copy link
Contributor

@mklement0 mklement0 Jul 8, 2020

Choose a reason for hiding this comment

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

This doesn't help, because the relative content path is ultimately still normalized in

normalizedTargetPath = Path.Join(SessionState.Internal.CurrentLocation.ProviderPath, strTargetPath.AsSpan().Slice(2));
- at least when I debug on macOS. Note that the relative path mustn't be used as-is: you must perform the equivalent of $relativePath -replace '[\\/]', [IO.Path]::DirectorySeparatorChar to normalize the separators.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, on a general note: I don't think it makes sense to ever interpret the target path as a wildcard pattern - see #13136

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Do you say about existent targets? In the case it is another issue. I don't change the behavior in the PR. I only address non-existent targets.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, this is about existing targets (too), as described in #13064, which your PR description notes as targeting (in addition to #9067); also, the need to normalize the path separators in relative paths applies to both existing and non-existing targets.

I'd say it makes sense to fix all these things together, but if you don't want to do that, please at least remove #13064 from the PR description.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I do not think that we can normalize non-existing targets safely. We can get unexpected results and can not check the targets.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm still confused: I also don't see why the .Target property shouldn't just use the target path as defined.
What reason is there to try to interpret it in any way?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It seems we say about different things.
Currently if we create a symlink with relative path the Target property will return absolute path but we expect a relative path used at creation time. Because of this one test fails in the PR on Unix-s.

Copy link
Contributor

@mklement0 mklement0 Aug 5, 2020

Choose a reason for hiding this comment

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

I pulled your PR, built it on macOS 10.15 and Ubuntu 18.04 and can confirm that it correctly creates symlinks with relative paths and performs separator normalization (and that .Target currently always reports the full path, assuming the target exists).

I'm still a bit confused about the .Target property: on Windows, it seemingly reports the target path as stored in the link. Why did we ever resolve it to a full path on Unix?

So your plan is to later change that and make it behave like it does on Windows?
But then you wouldn't need a call to realpath() at all, right?

Separately, knowing the full, resolved path is also useful, so we could consider adding a .ResolvedTarget property that always reports the full path, if it exists. For non-symlink items, it could report that item's own full path, which would enable you to target items uniformly by their ultimate target path.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@mklement0 Thanks!

So your plan is to later change that and make it behave like it does on Windows?
But then you wouldn't need a call to realpath() at all, right?

Yes, we should open new issue to track this.

Separately, knowing the full, resolved path is also useful

Please open new issue to discuss.

Copy link
Contributor

Choose a reason for hiding this comment

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

See #13365 and #13366.

@ghost
Copy link

ghost commented Jul 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

Comment on lines 333 to 335
if (-not $IsWindows) {
Set-ItResilt -Pending -Because "On Unix the Target property is always resolved to an absolute path."
}
Copy link
Collaborator

@vexx32 vexx32 Aug 6, 2020

Choose a reason for hiding this comment

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

If we need to mark this It as pending, we may want to separate the assertions into two separate tests.

Otherwise, the result will be confusing from this test (it might fail sometimes, but at most it will only be Pending in Mac/Linux).

Also, the cmdlet name is misspelled here. 🙂

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@vexx32 Thanks! I split tests.

@ghost ghost removed the Review - Needed The PR is being reviewed label Sep 15, 2021
@ghost ghost added the Review - Needed The PR is being reviewed label Sep 23, 2021
@ghost
Copy link

ghost commented Sep 23, 2021

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

// Don't support 'New-Item -Type Directory' on the Function provider
// if the runspace has ever been in constrained language mode, as the mkdir
// function can be abused
if (context.ExecutionContext.HasRunspaceEverUsedConstrainedLanguageMode &&
Copy link
Member

Choose a reason for hiding this comment

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

You should add a test case to cover this

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It is not new code. It is moved code.


if (type != null)
{
WildcardPattern typeEvaluator = WildcardPattern.Get(type + "*", WildcardOptions.IgnoreCase | WildcardOptions.Compiled);
Copy link
Member

Choose a reason for hiding this comment

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

I don't understand the use of the wildcardpattern here, type is a string for filesystem that should be symboliclink, junction, hardlink, etc... right? why isn't this a switch statement?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It is not new code. It is moved code.

@iSazonov iSazonov closed this Oct 4, 2022
@ghost ghost removed the Review - Needed The PR is being reviewed label Oct 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CL-General Indicates that a PR should be marked as a general cmdlet change in the Change Log Documentation Needed in this repo Documentation is needed in this repo
Projects
None yet
6 participants