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

WIP: Add support for side-by-side PS Core preview on Linux/macOS #1366

Merged
merged 6 commits into from
Jul 2, 2018

Conversation

rkeithhill
Copy link
Contributor

PR Summary

This PR supports listing the symlinks for pwsh & pwsh-preview.

Fixes #1361

The preferred default version is pwsh if both are present however, the
default will be pwsh-preview if it's installed and pwsh isn't.

So this only support side-by-side on Linux/macOS up to two versions:
stable and preview.

In the future, we may want to do what we do on Windows and search thru
the install dir for pwsh.
The would be /opt/microsoft/poweshell on LInux.
Not sure what it is on macOS.

Or maybe we should just do that now. Thoughts?

I marked this as WIP because I need someone to test this on Linux and macOS. :-)

PR Checklist

Note: Tick the boxes below that apply to this pull request by putting an x between the square brackets.
Please mark anything not applicable to this PR NA.

  • PR has a meaningful title
  • Summarized changes
  • This PR is ready to merge and is not work in progress
    • If the PR is work in progress, please add the prefix WIP: to the beginning of the title and remove the prefix when the PR is ready

This PR supports listing the symlinks for pwsh & pwsh-preview.

The preferred default version is pwsh if both are present however, the
default will be pwsh-preview if it's installed and pwsh isn't.

So this only support side-by-side on Linux/macOS up to two versions:
stable and preview.
Copy link
Member

@TylerLeonhardt TylerLeonhardt left a comment

Choose a reason for hiding this comment

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

LGTM, Keith 😄 just a small comment.

src/platform.ts Outdated
versionName: "PowerShell Core Preview",
exePath: linuxPreviewExePath,
});
}
Copy link
Member

Choose a reason for hiding this comment

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

I refactored this a bit to define the paths conditionally and then do the logic. I think it's a little DRY-er. Totally, not a blocker but what do you think?

let osExePath, osPreviewExePath;
if (platformDetails.operatingSystem === OperatingSystem.MacOS) {
    osExePath = macOSExePath;
    osPreviewExePath = macOSPreviewExePath;
} else if (platformDetails.operatingSystem === OperatingSystem.Linux) {
    osExePath = linuxExePath;
    osPreviewExePath = linuxPreviewExePath;
}

if ((defaultExePath === osExePath) && fs.existsSync(osPreviewExePath)) {
    paths.push({
        versionName: "PowerShell Core Preview",
        exePath: linuxPreviewExePath,
    });
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

LGTM. Can you make this change on the PR branch and merge? I think I've allowed it to be edited. If not, I should be able to get to this tonight.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated. Please test on macOS and Linux.

src/platform.ts Outdated
osPreviewExePath = linuxPreviewExePath;
}

if ((osExePath === defaultExePath) && fs.existsSync(osPreviewExePath)) {
Copy link
Member

Choose a reason for hiding this comment

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

It's super rare, but isn't it possible for them to have legacy (powershell) and preview (pwsh-preview)?

If so, this if check might have to be:

defaultExePath !== osPreviewExePath && ...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can fix this by testing for the legacy path here or maybe we should just remove support for the legacy "powershell"on Linux and macOS. This was abandoned somewhere around the transition from 6.0.0 alpha to beta. At this point, I'm not sure why anyone would still be running an alpha of 6.0.0 on Linux/macOS.

Copy link
Member

Choose a reason for hiding this comment

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

totally on board. We should only support 6.0.0 release and onward.

@TylerLeonhardt
Copy link
Member

Is there any work that needs to be done here:
https://github.com/PowerShell/vscode-powershell/blob/master/test/platform.test.ts

I just saw that it had to something with the exe path.

@rkeithhill
Copy link
Contributor Author

Those tests still pass for me on Windows. Looks like the tests mainly check to see that we get back the correct 32/64-bit version of Windows PowerShell on Windows.

@TylerLeonhardt
Copy link
Member

Sounds good :)

Copy link
Contributor

@rjmholt rjmholt left a comment

Choose a reason for hiding this comment

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

This is awesome! Thanks @rkeithhill!

Copy link
Contributor

@rjmholt rjmholt left a comment

Choose a reason for hiding this comment

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

I have yet to test this btw. Will do this week.

@TylerLeonhardt
Copy link
Member

TylerLeonhardt commented Jun 27, 2018

So I was messing with the VSCode & PowerShell snaps... Snap is essentially an attempt at a "universal *nix package manager... more info here. Snap is a Canonical thing

Anyway... on all of their supported OS's you should be able to run:

sudo snap install --classic vscode
sudo snap install --classic powershell
code --install-extension="ms-vscode.powershell"

and get VSCode, PowerShell and the extension installed...

However the extension fails because the "powershell exe" it is trying to use is /usr/bin/powershell but that doesn't exist... Snap does something different:

PS /home/parallels/Desktop> which powershell                                    
/snap/bin/powershell
PS /home/parallels/Desktop> which pwsh                                          
/snap/powershell/2/opt/powershell/pwsh

NOTE: the 2 in the which pwsh changes every version... apparently we can replace 2 with current and it resolves.

we should probably handle this in the linux case so we can support the Snap build of PowerShell out of the box.

@rkeithhill would you be ok adding a check for this in this PR?

@rkeithhill
Copy link
Contributor Author

Are those paths on Linux or macOS? Also, is the binary called powershell?? Or is that just a dir name? I thought the binary would be either pwsh or pwsh-preview. And speaking of PowerShell preview, do we need to handle that case with snap?

@TylerLeonhardt
Copy link
Member

@rkeithhill AFAIK, snap is only linux:
image

@TylerLeonhardt
Copy link
Member

TylerLeonhardt commented Jun 27, 2018

the binary is called pwsh found here:
/snap/powershell/2/opt/powershell/pwsh but we can rely on:
/snap/bin/powershell or /snap/bin/pwsh (I prefer pwsh)
which are symlinks

and we should also handle the pwsh-preview scenario for snap as well:
/snap/bin/pwsh-preview

@TylerLeonhardt
Copy link
Member

I've been talking to @TravisEz13 about this who has been driving the Snap work

@TylerLeonhardt
Copy link
Member

TylerLeonhardt commented Jun 27, 2018

I can't wait to install VSCode & PowerShell on my OpenWRT based Router lol

@rkeithhill
Copy link
Contributor Author

@tylerl0706 Can you test this in a Snap environment?

@TylerLeonhardt
Copy link
Member

gladly :) I'll test now.

@TylerLeonhardt
Copy link
Member

@rkeithhill it works!

src/platform.ts Outdated
osExePath = macOSExePath;
osPreviewExePath = macOSPreviewExePath;
} else if (platformDetails.operatingSystem === OperatingSystem.Linux) {
osExePath = linuxExePath;
Copy link
Member

Choose a reason for hiding this comment

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

do we not need to do the same ternary op here to check for snap?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not needed here because getDefaultPowerShellPath already returns just one of: linuxExePath, linuxPreviewExePath, snapExePath, snapPreviewExePath. It searches in that order.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

BTW I get the impression (perhaps incorrect impression) that on a Snap system, PowerShell will only be at /snap/bin/pwsh* and that you wouldn't also have PowerShell at /usr/bin/pwsh*. And on a straight (non-Snap) Linux system, there would be no /snap/bin/pwsh*. That is, these two sets are mutually exclusive. Is that correct?

Copy link
Member

Choose a reason for hiding this comment

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

So snap is really just a package manager that you first install with apt. So you could have installed pwsh by Snap and Apt on the same system.

Not quite sure why one would do that... but it's physically possible. I guess I could see something along the lines of installing pwsh with apt and pwsh-preview with snap maybe...

So it's physically possible to have a /snap/bin/pwsh and a /usr/bin/pwsh.

Copy link
Member

Choose a reason for hiding this comment

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

However! I just learned that /snap/bin/powershell gets created but /usr/bin/powershell does not. So if you installed PowerShell with Snap and Apt, typing pwsh at the terminal will get you the apt version... and typing powershell at the prompt will get you the Snap version.

This might be TMI but I figured I would share.

@TylerLeonhardt
Copy link
Member

TylerLeonhardt commented Jun 28, 2018

You might hate me for saying this... but I've thought about this part of the code for a bit and wonder if there's some opportunity to clean up the code a bit...

maybe something like this:


function getAvailablePowerShellExes() {
    let exes = [];
    
    if(Windows) {
        ... similar as below
    }
    if(macOS) {
        ... similar to below
    }
    if(Linux) {
        linuxExes = ["/usr/bin/pwsh", "/snap/bin/pwsh", "/usr/bin/pwsh-preview", "/snap/bin/pwsh-preview"]
        linuxExes.forEach((exe) => {
            if(exe exists) {
                exes.push(exe);
            }
        });
    }
    return exes;
}

function getDefualtPowerShellExe() {
    return getAvailablePowerShellExes()[0];
}

Note that the array is in the order of what we consider the default.
Also that this is psuedocode :)

if we're super worried about perf (in this case, I don't think we are) we could optionally give getAvailablePowerShellExes a parameter bool called stopAtFirstExe that will break out of the for loop when it finds a valid exe.

I wont block on this, but I feel like it might be worth it...

@rkeithhill
Copy link
Contributor Author

Not at all. I have no particularly affinity for this code. :-) We could make that change but we can't get rid of the test against the default PowerShell exe simply because we don't want the same entry to show up twice. Also, I don't think perf is that much of a concern here and we do want to list all the available PowerShell instances that can be used.

@TylerLeonhardt
Copy link
Member

Thanks for putting up with my comments 😄

We could make that change but we can't get rid of the test against the default PowerShell exe simply because we don't want the same entry to show up twice

I don't think I quite follow how we would end up with something showing up twice? Think you could elaborate?

@rkeithhill
Copy link
Contributor Author

The issue is that for some reason (I don't remember) in the current impl of getAvailablePowerShellExes we use getDefaultPowerShellPath to get at least the one path we know will be on the system. But we could probably remove that and simplify the impl. That said, I don't think we can use the first result of getAvailable for getDefault because getDefault takes an extra parameter - use32 - which on Windows 64-bit, requests the 32-bit version of PowerShell.

@rkeithhill
Copy link
Contributor Author

Updated to simplify per your suggestion. Can you test again on Linux/macOS?

@TylerLeonhardt
Copy link
Member

@rkeithhill no surprise your code works beautifully :)

@rkeithhill rkeithhill merged commit 0c7c1bd into master Jul 2, 2018
@rkeithhill rkeithhill deleted the rkeithhill/add-pwsh-preview-support branch July 2, 2018 23:44
rjmholt pushed a commit that referenced this pull request Jul 11, 2018
* Add support for side-by-side PS Core preview on Linux/macOS

This PR supports listing the symlinks for pwsh & pwsh-preview.

The preferred default version is pwsh if both are present however, the
default will be pwsh-preview if it's installed and pwsh isn't.

So this only support side-by-side on Linux/macOS up to two versions:
stable and preview.

* Adjust name of default PS Core on Linux/macOS

* Make a bit DRY-er. Thx @tylerl0706

* Remove support for pre-ship PS Core Linux/macOS binary name - powershell

* Add support for PowerShell Core installed in a Snap

* Simplify impl of getting available PS on Linux/macOS
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

PowerShell preview executables no longer at /usr/[local/]bin/pwsh on *nix
3 participants