sdkman / sdkman-cli

The SDKMAN! Command Line Interface
https://sdkman.io
Apache License 2.0
6.07k stars 628 forks source link

It should be possible to use system artifact instead of sdkman's #673

Open cardil opened 5 years ago

cardil commented 5 years ago

Please tick one:

Please explain the Issue / Feature Request here:

It's currently impossible, after using sdkman, to restore Java to use default installed in operation system. It should be possible to do that, even temporarly.

It's done this way by multiple tool version managers like:

I think sdkman could simply remove current binding for a tool with special command, removing current symlink for example:

sdk use java system

or

sdk unuse java

marc0der commented 5 years ago

Allow fallback to system installation of SDK

marc0der commented 5 years ago

I've got to say that I really like the idea of introducing the new unuse command here. I'd expect it to work as an opposing force to the use command ie. it only affect the current shell.

In addition I would introduce another new command as counterpart to the default command, and call that system. ie. affects all subsequent shells that are opened.

So, this is what you would have:

$ sdk system java     # use system java in all shells
$ sdk default java    # use sdkman java in all shells

$ sdk unuse java      # use the system java only in this current shell
$ sdk use java        # use sdkman java in the current shell

Does this sound like an acceptable approach to everyone?

cardil commented 5 years ago

I must admit I rather like the other approach:

$ sdk use java 8-zulu   # use sdkman java 8 in shell
$ sdk use java system   # use os java in shell

$ sdk default java 11-zulu # use sdkman java 8 in all future shells
$ sdk default java system  # use system java in all future shells

I think I just more used to that approach in other tools like rvm or pyenv. It's also more in line with other commands of sdkman. I think it will be easier to remember for users.

But adding two new commands is just fine as well.

It's basically the choosing between:

vmj commented 5 years ago

+0 for virtual version.

marc0der commented 5 years ago

@vmj did you mean +1? 😀

vmj commented 5 years ago

@marc0der 😄 no, I meant "I don't feel strongly, but if this happens, the virtual version seemed more natural".

But now that I think about it more, what would the "system" version be for candidates that do not have any system counterpart or have multiple? It's probably "whatever the system was set up it to be". I.e. sdkman will just step aside and let things be as messy as they were before it.

In that case, I feel that unuse/system commands might be a bit easier to understand:

So yes, I'm changing my vote to "+0 for new commands". Sorry 😜

But maybe the name of the system command should be something like hide or disable. system is not a verb and sdk system java sounds like a script around /path/to/system/java --version.

marc0der commented 5 years ago

@vmj no worries! thanks for clarifying. And yes, good point about system not being a verb.

cardil commented 5 years ago

If you are going for new methods maybe better names will be:

use - unuse default - undefault

As you see, default is also not a verb.

Maybe change to set-default and unset-default.

marc0der commented 5 years ago

@cardil we are using default as a verb in this context. ie we default java to 11.0.1. We also won't be changing that any time soon as it is already widely used by all. I like the idea of introducing undefault as counterpart to default though.

ghost commented 5 years ago

But now that I think about it more, what would the "system" version be for candidates that do not have any system counterpart or have multiple?

Why not simply check if it exists and if there is no system-wide available installation then ask user’s confirmation if that is surely what is wanted?

For multiple choices, sdk can use the system’s alternatives/default resolution tool to show current OS default version like update-alternatives does in Ubuntu for an example.

Hm… maybe sdk can use system alternatives/default configuration tools to show system version in listing as well while using new version marking like “s” (lowercase) for system-wide available and “S” (uppercase) for currently set system wide default version in addition to “+” and “*”?

marc0der commented 5 years ago

For multiple choices, sdk can use the system’s alternatives/default resolution tool to show current OS default version like update-alternatives does in Ubuntu for an example.

Introducing a dependency on tools that are available only on certain platforms is not good because we would need to start maintaining code branches for every platform under the sun. At the moment sdkman is decoupled as much as possible from it's environment and I think we should keep it that way. Therefore I'm not in favour of depending on tools like update-alternatives on Ubuntu or /usr/libexec/java_home on mac.

Why not simply check if it exists

It's not that simple. We don't know what we are checking for as sdkman is completely agnostic of the contents of the sdks that it serves. ie. we don't know (and don't want to care) what's in the bin folder of each candidate, so we are not even aware that java, scala, groovy, kotlin executables are provided by sdkman.

cardil commented 5 years ago

Uprate-alternatives requires root access. Sdkman is user space program, it shouldn't rely on update-alternatives.

System option is pretty good option even you got nothing installed on system. You are using system, but there nothing there so it effectively unset a tool and disable it's usage.

martin-walsh commented 5 years ago

Came across the need to do this today...

I have Oracle JDK 7 & 8 installed on mac using the installer(s) and OpenJDK 10 & 11 using sdkman.

Switching back to either of the "system" versions after switching to sdk managed version requires mucking about with the PATH

+1 for unuse

marc0der commented 5 years ago

@martin-walsh That is absolutely not necessary. Simply use sdkman's local version feature: https://sdkman.io/usage#localversion

hickst commented 5 years ago

@marc0der The local version feature does not seem to work as documented in https://sdkman.io/usage#localversion I tried sdk install groovy 2.4.13 /usr/local/src/groovy-2.4.13 from a local version. Instead of linking (or even copying) the existing installation, sdkman downloaded and installed a new copy of 2.4.13 in candidates/groovy/2.4.13/ I tried several other versions of Groovy, Java, etc....same problem. Also, I note the help for sdk install does not list a possible 4th argument to an existing path. Currently trying this with version SDKMAN 5.7.3+337

martin-walsh commented 5 years ago

Local feature works a charm for me on macOS!

sdk install java 7 /Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home/

SDKMAN 5.7.3+337

marc0der commented 5 years ago

@hickst It certainly is working. Try using a version that is unique. I think 2.4.13 is taken, so maybe try something like 2.4.13-local.

hickst commented 5 years ago

Success! Thanks for clarifying how it works. The fact that you cannot use the same name as sdkman really should be in the documentation, though. Otherwise, the natural tendency is to follow the naming pattern used by the tool, which results in the failure to create a local link. Also, the help documentation for the install command should be updated to show the optional 4th argument (the existing installation path). Thanks again.

marc0der commented 5 years ago

Even better, maybe sdkman itself should tell you that it is a reserved version string. Wdyt?

hickst commented 5 years ago

@marc0der Yes, having the tool itself help one to do it correctly definitely sounds like the best idea.

I also recommend a "local" Java example in the documentation, similar to the one @martin-walsh showed above (thanks for the help @martin-walsh!)

marc0der commented 5 years ago

@hickst afaik, it is already documented.

Regarding letting the tool itself help you do it correctly, want to raise a PR for that one?

hickst commented 5 years ago

@marc0der which "it" is already documented? In the documentation for Install Local Version(s), I see only a single Groovy example. I am recommending that:

  1. we add text, in that section, to clarify that the "local" name one selects may not be the same as any version that sdkman already uses,
  2. we add a Java example, similar to the one given above. For example: sdk install java 10-zulu-local /Library/Java/JavaVirtualMachines/zulu-10.jdk/Contents/Home
  3. we update the sdkman usage (help) strings to show the optional 4th argument. For example:
    commands:
       install   or i    <candidate> [version]
    ...

    would become

    commands:
       install   or i    <candidate> [version] [path-to-local-installation]
    ...
hickst commented 5 years ago

@marc0der I would be happy to open a new issue but do we need to move this discussion to Gitter before I am allowed to do that?

marc0der commented 5 years ago

Don't worry about the gitter discussion. You can update the website docs in this project with a PR: https://github.com/sdkman/sdkman-website

Of course the help can be updated in this project.

jamesdh commented 5 years ago

May I also suggest an unset option, for those packages which don't have system artifacts?

E.g. sdk unset grails to effectively unlink any version of grails that's currently configured, but lasts beyond the current shell and doesn't force me to uninstall the various versions installed?

marc0der commented 5 years ago

@jamesdh that might be confusing for users as the set command is used for changing versions in the current shell only.

jamesdh commented 5 years ago

@marc0der isn't that use?

In any case, it'd be nice to somehow remove any link to an installed version without actually uninstalling.

marc0der commented 5 years ago

@jamesdh yes you're right, my bad.

ieugen commented 4 years ago

I would also like to express my support for this functionality.

I've installed graalvm with sdk to play around with native compilation. However, on (nodejs) project was failing to build with graal's node . The only way I could get past this was to uninstall graalvm.

If there was an option to disable/unset sdk graal then I could have avoided the un-instalation.

I do hope sdkman implements this functionality. It is necessary.

marc0der commented 4 years ago

@ieugen a better workaround is probably to install the default JDK (AdoptOpenJDK) and make that your system default. Then you shouldn't have any conflicts with Node. You can then apply the sdk use command to switch to Graal in individual terminals when you require it. Hope that helps!

ieugen commented 4 years ago

Thanks that is a good suggestion. I do have an issue with it. I already have adoptopenjdk installed via Debian package system. I do prefer that since I have unattended-upgrades in place. In this case I might go for this workaround if I can use both and experiment. I do prefer Debian packages since they are better integrated with the system.

ieugen commented 4 years ago

Some feedback. The sdk use java XXX method works. However I still need to keep the java version installed in Debian since I have other packages that depend on it.

This does/can create some issues:

bjoernv commented 3 years ago

Using a localversion Java also worked for me. I am still unhappy about the fact, that sdkman sets JAVA_HOME to ~/.sdkman/candidates/java/current if I wish to use the system Java. I wish a solution which lets JAVA_HOME as it is defined by the system.

Hero9909 commented 2 years ago

Ive discovered that a simple aproach is to use an bash function to enable sdkman, just enclose the 2 sdkamn lines into a function and call them if you need sdkman, but once loaded i dont know how a clean way to unload it would look like.

prameshbhattarai commented 2 years ago

I was able to link system java sdk to sdkman using Install local version https://sdkman.io/usage#localversion. And sdkman was able to list my system java and I switched it.

For example: Adding system sdk to sdkman

# sdk install unique_name_of_sdk path_to_system_sdk
sdk install java-8-openjdk /usr/lib/jvm/java-8-openjdk-amd64/

Apply the local sdk version

sdk default java-8-openjdk

List all java version from sdk Output:

--------------------------------------------------------------------------------
Offline: only showing installed java versions
--------------------------------------------------------------------------------
 > java-8-openjdk
 * java-11-openjdk
 * 17-open
--------------------------------------------------------------------------------
* - installed                                                                   
> - currently in use                                                            
--------------------------------------------------------------------------------
meden commented 1 year ago

Any news on this?

sdkman is basically breaking my Debian system, insisting in wanting to set its own JAVA_HOME, after I set a default by cli. I did not know the change was basically irreversible... (unless uninstalling sdkman, and cleaning the .bashrc.

hron84 commented 5 months ago

Under Arch Linux, there is a way to create the virtual system version by

sdk install java system /usr/lib/jvm/default

Since /usr/lib/jvm/default is a symlink managed by archlinux-java command and where it points is the default java on the specific system.

However, it would be much nicer if SDKMan rather can roll back the changes in the environment regarding to the Java Runtime, and let system's default behavior happen whatever is that.