eselect-wine implementation notes
=================================

Just bit of ramblings, nothing interesting for most people here
unless want an overview to work on the module or rewrite again.

Ideas
-----
* ``/usr/bin`` wrappers:
   - pros: mininal need for changes, and could select like python-exec
     with ``/etc`` configs and/or env vars
   - cons: we don't know what wrappers are needed, wine variants or
     versions could use more binaries or less and become messy to handle,
     plus still need to handle man pages and such

* ``PATH``/``MANPATH``/``XDG_DATA_DIRS``-based:
   - pros: *mostly* no modifications needed bare normal ``/etc/env.d`` files
   - cons: does not handle some still needed ``/usr`` links and users have to
     ``source /etc/profile`` every single updates(!) for new ``PATH``, also
     ``PATH`` use in general could become an issue if used by too many eselect
     modules (not that it's so bad if just used by packages with many bins)

* ``/usr`` live symlinks/updates (legacy model):
   - pros: no sourcing ``/etc/profile`` ever fwiw
   - cons: requires some degree of safety to know what we can touch, so
     former ``eselect-wine`` used a register/deregister model, hardcoded
     known variants, and saved links in config files (error prone and
     sometimes left users needing to manually fix it at times, modifying
     live ``/usr`` is also often frowned upon and this overdid it)

* ``PATH``-based with ``/etc/eselect/wine/bin`` links (current):
   - pros: no need to ``source /etc/profile`` more than once, and does not
     modify ``/usr`` (``/usr/bin/wine`` link can be installed by the ebuild
     for e.g. ``binfmt`` compat), ``/etc/eselect/wine`` can be deleted safely
     and re-generated cleanly on a whim
   - cons: sourcing ``/etc/profile`` once still requires informing users, and
     implementation still a bit complex despite half+ size of the previous

Notable ebuild installation paths
---------------------------------
* ``usr/include/wine-<variant>-<version>`` (-> ``/usr/include/wine`` for compat)
* ``usr/lib/wine-<variant>-<version>``
   - ``bin/`` (usable in ``PATH`` as-is, but will lack variant links)
   - ``wine/`` (-> ``/usr/lib/wine`` for compat, albeit this one is not
     typically needed given ``winebuild`` will find the right location)
* ``usr/share/wine-<variant>-<version>`` (usable as ``XDG_DATA_DIRS``)
   - ``man/`` (usable in ``MANPATH``)
* ``usr/bin/*-<variant>-<version>`` (optional, not used *here* anymore)

Legacy ebuilds may split between ``usr/lib64`` and ``usr/lib``, i.e. rather than
have ``wine/{i386,x86_64}`` in ``/usr/lib/<slot>``, will be split as such:

* ``usr/lib/<slot>/wine/i386-windows``
* ``usr/lib64/<slot>/wine/x86_64-windows``

(not supported anymore, current eselect will warn they are being ignored)

If need to auto-detect installations, it is recommended to check if
``usr/lib/wine-*-[0-9]*/bin/wine`` exists and use the matching ``wine-*``
to look at other directories (variant name should not have ``-``).

Current implementation overview
-------------------------------

``eselect-wine`` ebuild's env.d adds ``/etc/eselect/wine/bin`` to ``PATH``,
and similar for ``MANPATH``/``XDG_DATA_DIRS`` which provides static
locations that will not need ``source /etc/profile`` every changes.

Can freely work on that directory, clean it up, add variants suffixes,
etc... without worrying about mangling ``/usr``.

Like previous implementation, still allows per-variant versioning, e.g.

* ``winecfg-vanilla`` -> ``/usr/bin/wine-vanilla-7.0`` (shell wrapper)
* ``winecfg-vanilla-7.0`` -> ``/usr/lib/wine-vanilla-7.0/bin/winecfg``
* ``winecfg`` -> ``/usr/bin/wine-vanilla-7.0`` (*could* be a symlink to ^)

Versioned wrappers like ``winecfg-vanilla-7.0`` are installed by Wine
ebuilds and can be modified *there* if any quirks need to be handled.
So, for consistency, calling the wrapper even for plain ``winecfg``.

Wrappers are needed because wine treats ``argv[0]`` specially. May be
workable around for a pure ``PATH`` solution, but would likely require
yet more ``eselect-wine`` compatibility code in ebuilds. Alternatively,
could consider removing variant link support altogether.

Originally wanted to not have a ``wine.conf`` and read links for the
previous slots and updates, but unless wrappers are in ``/usr/lib/<slot>``
that would be unreliable.

These aside, ``eselect-wine`` ebuild will have created ``/usr/bin/wine``,
``/usr/lib/wine``, and ``/usr/include/wine`` symlinks that points to
locations in ``/etc/eselect/wine``. This allows updating them without
modifying ``/usr`` directly. Would be possible to work without these
but may confuses some build systems and ``/usr/bin/wine`` is a typical
location for ``binfmt`` to look at.

``XDG_DATA_DIRS`` is not currently very useful (only one .desktop), but
would be relevant if want to move things back from ``wine-desktop-common``.

One issue about ``.desktop`` is that legacy eselect used to handle
``update-desktop-database``. Given it's now a private cache file only
created for Wine in ``/usr/share/<slot>/applications`` it may make more
sense to have ebuilds generate it in ``src_install()`` (tracked, allowing
cleanup and directory removal). Not that missing cache for 1 ``.desktop``
means much. Also, per-variant ``XDG_DATA_DIRS``/``.desktop`` is not handled
(aka only main is active), this would be messy as far as MimeTypes
priorities go anyway.

ebuilds only need to run a single ``eselect wine update --if-unset`` in
``src_postinst`` and ``src_postrm`` (yes **post** rm now), no registering
process.

Migration handling
------------------

Need some degree of compatibility with older ``eselect-wine`` given older
installed Wine ebuilds or those from overlays will call this in e.g.
``src_prerm()`` with old arguments (could sit there for years).

To complicate things, in ``prerm`` the files still exists and so we end up
auto-detecting them and not actually cleaning.

So, still recognize these:

* ``register``: no-op, return true
* ``deregister``: likewise
* ``update``: ignore e.g. ``--all``/``--vanilla`` arguments, some ebuilds
  may end up updating twice until migrated but that's ok

``unset`` also existed, but to my knowledge only the ``eselect-wine`` ebuild
ever used this (``prerm``) and this should never be used with the new one.

``eselect-wine`` ebuild can handle calling the old one for most cleanups,
additionally ``active`` -> ``eselect-wine-migration`` is supported to attempt
to keep same slots selected. Users will need to ``source /etc/profile`` (once)
for ``PATH`` updates, but otherwise *should* see no negative impacts.

Support code for these can be cleaned up in 2025 or later, no urgency
albeit it will cleanup ``eselect wine help`` output and tidy the
``eselect-wine`` ebuild. Meanwhile Wine ebuilds are encouraged to ``IDEPEND``
on ``>=app-eselect/eselect-wine-2`` and drop deprecated usage.

Normally migration should be smooth, but there is no mechanism implemented
to cleanup ``/usr/bin`` and ``/usr/share/man`` with an old version's **broken**
``/etc/eselect/wine`` (e.g. missing data while links are still in ``/usr/bin``).
Searching for dead links may help if needed (e.g. ``find /usr/bin -xtype l``).
Fortunately, dead links are normally ignored in ``PATH`` and won't shadow.

Note downgrading ``eselect-wine`` after migrating is not very supported as it
requires re-registering each slots again manually. Re-upgrading should not
be an issue though.
