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

Small refactoring and fixes to opam init on Windows. #6000

Merged
merged 15 commits into from
Jun 10, 2024

Conversation

dra27
Copy link
Member

@dra27 dra27 commented Jun 6, 2024

At present includes #5991, #5994 and #5997. The diff becomes slightly less hideous with #5997 merged. The PR includes the behaviour of #5996 and may need #5998 for CI to pass properly.

This PR considerably extends the ideas from #5963. The primary goal is to extend opam init on Windows to recognise as many scenarios for getting either Cygwin or MSYS2 as we at present know to exist, so that users are presented with meaningful choices. In particular, this addresses running opam init from with a Cygwin or MSYS2 bash shell (in particular, #5952 is fixed).

I think it's helpful to start with some scenarios with beta2, and then explain the fixes from there:

  1. From cmd/pwsh, with nothing other than opam installed, we already have an excellent experience which recommends pausing to install Git for Windows (with helpful advice on that added Improvements to opam init "Git" menu on Windows #5963) and which installs Cygwin.
  2. If the user has installed Git for Windows using its (non-default) "Use Git and optional Unix tools from the Command Prompt" setting (or run choco install git /GitAndUnixToolsOnPath), then beta2 displays rather more Git options than might be nice, but Improvements to opam init "Git" menu on Windows #5963 also makes this a quite elegant experience by default (the bash.exe included on PATH is correctly shadowed by the internal Cygwin installation, which is recommended).
  3. If the user installs things with Scoop - e.g. scoop install cygwin msys2 git - then opam init presently works, but neither Git for Windows, MSYS2 or Cygwin are recognised by opam.
  4. Similarly, if the user installs with Chocolatey - e.g. choco install cyg-get msys2 git - then opam init does detect Git for Windows, but does not detect either the MSYS2 or Cygwin installations.
  5. Similarly, if the user installs with winget - e.g. winget install Cygwin.Cygwin MSYS2.MSYS2 Git.Git - then we have an experience similar to Chocolatey, although as Cygwin is installed to the default C:\cygwin64, that is recognised by opam.
  6. If the user runs opam init from Git Bash (not a recommended thing to do), then we get hit by Harden curl output parsing #5984, but if we work around that then the experience is OK. This is a scenario where there are tools on the PATH, and running with --no-cygwin-setup is not as OK - opam var os-distribution reporting win32 instead of msys2. That said, using Git Bash to run opam init is never going to be a good idea (it has no package manager - it's intended for interaction with Git only).
  7. If the user has elected to configure their PATH to have MSYS2's main bin directory permanently installed, then the default behaviour of opam init is pretty good, unless MSYS2's curl shadows Windows curl.
  8. If the user runs opam init from within MSYS2's bash the experience both with and without --no-cygwin-setup is pretty good.
  9. If the user has elected to configure their PATH to have Cygwin's main bin directory permanently installed, then the default behaviour is affected by opam init --cygwin-internal-install is ignored from cygwin terminal #5952.
  10. Running opam init from within Cygwin's bash is similarly affected by opam init --cygwin-internal-install is ignored from cygwin terminal #5952.

In all of these scenarios where the user has preinstalled either MSYS2 or Cygwin, we do have the issue that opam init --no-cygwin-setup (i.e. just using what's found) will typically fail because patch, unzip and so forth are not installed by default.

The changes here seek to make all of those scenarios as awesome as possible.

At a very high-level the changes are:

  • MSYS2 and Cygwin are now treated equally where sys-pkg-manager-cmd is concerned (if both have been defined, Cygwin takes priority). In particular that means that MSYS2 gets added to PATH in exactly the same way as Cygwin.
  • os-distribution is no longer explicitly set by opam init. Instead, os-distribution is always determined by looking at cygpath.exe. The internal or --cygwin-location treatment merely affects PATH resolution (i.e. the internal cygbin addition) - once cygpath.exe is resolved, it becomes the source of truth. Thus, from an MSYS2 shell, opam var os-distribution is now msys2 by default.
  • For now, I've removed the prompting for Cygwin setup. The idea here is that we treat Cygwin setup as being equal between both an internal and external installation of Cygwin. In particular, this fixes a bug in depext treatment when initialising with --cygwin-location as Cygwin setup was never downloaded.
  • The final, somewhat horrific, refactor in OpamClient attempts to deal with the fact that the Git menu and the Unix tools decisions are not independent. The Unix tools are now determined first, and that feeds into the decision about what may need to be done for Git.
  • Various tricks are now exploited to find Cygwin and MSYS2 installations:
    • Cygwin's two registry keys are inspected
    • The default locations of C:\cygwin64 and C:\msys64 are used
    • A path search for msys2.exe provides an heuristic for seeeking an MSYS2 installation
    • Special handling for Scoop is added, both to identify its Git for Windows and to identify its MSYS2 installation
  • A key feature of all of these changes is that we only ever cygcheck and cygpath while inspecting things. In particular, we have to be very careful about running bash since we have no idea what it may do.
  • Chocolatey and winget both correctly initialise their MSYS2 installations, but unfortunately Scoop leaves this as an instruction to the user. Again, I've added some special handling to detect this - but this is treated just as running a depext command, so opam asks about it first.
  • The depext system is now integrated into opam init so opam will offer to add the required packages to both Cygwin and MSYS2 for existing installations, rather than simply erroring.

Put together, the changes mean that the user is presented with meaningful choices in all 10 of those scenarios and, in particular, they will see all of the packages they have already installed. If they agree with everything opam suggests, they should then always end up with initialised opam with a compiler 🥳

On my system, when added to #5992, opam init run from Cygwin's bash now offers:

DRA@Tau /cygdrive/c/Devel/opam
$ ./opam init

<><> Unix support infrastructure ><><><><><><><><><><><><><><><><><><><><><>  🐫

opam and the OCaml ecosystem in general require various Unix tools in order to operate correctly. At present, this requires the installation of Cygwin to provide these tools.

How should opam obtain Unix tools?
> 1. Use tools found in PATH (Cygwin installation at C:\cygwin64)
  2. Automatically create an internal Cygwin installation that will be managed by opam (recommended)
  3. Use Cygwin installation found in C:\cygwin64
  4. Use Cygwin installation found in C:\OCaml64
  5. Use Cygwin installation found in C:\cygwin64-2
  6. Use Cygwin installation found in C:\Users\DRA\AppData\Local\opam\.cygwin\root
  7. Use Cygwin installation found in C:\Devel\Roots\beta2-testing\.cygwin\root
  8. Use Cygwin installation found in C:\Cygwin64-beta2-testing
  9. Use Cygwin installation found in C:\cygwin64-throw
  a. Use Cygwin installation found in C:\Devel\Roots\opam-testing\.cygwin\root
  b. Use Cygwin installation found in C:\Devel\Roots\final-test\.cygwin\root
  c. Use Cygwin installation found in C:\Devel\Roots\env-testing\.cygwin\root
  d. Use Cygwin installation found in C:\cygwin64-throw2
  e. Use Cygwin installation found in C:\Devel\Roots\msys2-native\.cygwin\root
  f. Use Cygwin installation found in C:\Devel\Roots\os-dist-cygwin\.cygwin\root
  g. Use MSYS2 installation found in C:\msys64
  h. Use another existing Cygwin/MSYS2 installation
  i. Abort initialisation

[1/2/3/4/5/6/7/8/9/a/b/c/d/e/f/g/h/i]

@rjbou rjbou added this to the 2.2.0~beta3 milestone Jun 6, 2024
@rjbou rjbou self-requested a review June 6, 2024 09:23
@kit-ty-kate kit-ty-kate added the PR: QUEUED Pending pull request, waiting for other work to be merged or closed label Jun 6, 2024
@dra27 dra27 force-pushed the revised-windows-init branch 5 times, most recently from 22be138 to fbf5a9e Compare June 6, 2024 20:44
src/state/opamSysPoll.ml Outdated Show resolved Hide resolved
src/client/opamClient.ml Outdated Show resolved Hide resolved
src/client/opamClient.ml Outdated Show resolved Hide resolved
@dra27 dra27 force-pushed the revised-windows-init branch 5 times, most recently from 13850da to 4697b20 Compare June 7, 2024 10:48
@dra27 dra27 linked an issue Jun 7, 2024 that may be closed by this pull request
@dra27 dra27 removed the PR: QUEUED Pending pull request, waiting for other work to be merged or closed label Jun 7, 2024
@kit-ty-kate kit-ty-kate mentioned this pull request Jun 7, 2024
3 tasks
Previously, --git-location was treated as a default answer for the Git
menu, so it would display an error if Git wasn't found, but then simply
exit and fallback to adding Git to the Cygwin installation. Fix this
and validate either --git-location argument or the git-location opamrc
field as referring to a directory which contains Git.
Rather than filtering git out of the package list, instead add it when
required.
Make the ~cygbin parameter to the various executable identification
functions optional. The parameter is renamed to search_in_first with a
slightly revised semantics - if cygcheck.exe is not found in the
directory, then PATH is still searched.

This has a key benefit early on in opam init, as it allows cygbin to be
set for an internal Cygwin installation which has not yet happened, but
still permits curl (et al) to be used from PATH (e.g. when running opam
init from an MSYS2 shell).

Where before ~cygbin implied that cygcheck _must_ be used from the
directory, the new parameter effectively prepends an additional
directory to PATH.
Previously, MSYS2 required os-distribution to be overridden in
global-variables. Now, as with Cygwin, it is inferred in the same way
from cygcheck.

In this commit, opam init still sets os-distribution, however, if it is
manually removed from the root config file, previously `opam var
os-distribution` would return `win32` but now returns `msys2`.

Additionally, sys_pkg_manager_cmd is handled in the same way for MSYS2
as for Cygwin, allowing MSYS2 to be automatically added in the same way
as Cygwin.
Single argument function with a non-base type.
Includes more checks and also returns the kind of installation which was
found.
The ability to copy setup-x86_64.exe is no longer needed - but restore
the previous functionality which only downloaded setup if it didn't
exist and use this when displaying a command to the user. In this mode,
we only download setup-x86_64.exe so that the command we give to the
user actually works.

If we're actually going to run setup-x86_64.exe, then we download the
latest version.
Copy link
Collaborator

@rjbou rjbou left a comment

Choose a reason for hiding this comment

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

What a small refactoring!! :D it's working smoothly, thanks!

@kit-ty-kate
Copy link
Member

Thanks!

@kit-ty-kate kit-ty-kate merged commit 4f1e29a into ocaml:master Jun 10, 2024
39 checks passed
@kit-ty-kate kit-ty-kate mentioned this pull request Jun 11, 2024
@dra27 dra27 mentioned this pull request Jun 13, 2024
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.

opam init --cygwin-internal-install is ignored from cygwin terminal
3 participants