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

installer: add option for external GnuPG #480

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Okeanos
Copy link
Contributor

@Okeanos Okeanos commented Feb 11, 2023

This pull request addresses git-for-windows/git/issues/3997 by adding an additional detection mechanism for externally supplied GnuPG binaries to a new choice page in the installer and allows the user to "skip" the installation of the bundled GPG related binaries.


Notes:

The full list of stuff that will not be installed (pacman -Ql gnupg):

gnupg /usr/
gnupg /usr/bin/
gnupg /usr/bin/addgnupghome
gnupg /usr/bin/applygnupgdefaults
gnupg /usr/bin/dirmngr-client.exe
gnupg /usr/bin/dirmngr.exe
gnupg /usr/bin/gpg-agent.exe
gnupg /usr/bin/gpg-connect-agent.exe
gnupg /usr/bin/gpg-wks-server.exe
gnupg /usr/bin/gpg.exe
gnupg /usr/bin/gpgconf.exe
gnupg /usr/bin/gpgparsemail.exe
gnupg /usr/bin/gpgscm.exe
gnupg /usr/bin/gpgsm.exe
gnupg /usr/bin/gpgsplit.exe
gnupg /usr/bin/gpgtar.exe
gnupg /usr/bin/gpgv.exe
gnupg /usr/bin/kbxutil.exe
gnupg /usr/bin/watchgnupg.exe
gnupg /usr/lib/
gnupg /usr/lib/gnupg/
gnupg /usr/lib/gnupg/gpg-check-pattern.exe
gnupg /usr/lib/gnupg/gpg-preset-passphrase.exe
gnupg /usr/lib/gnupg/gpg-protect-tool.exe
gnupg /usr/lib/gnupg/gpg-wks-client.exe
gnupg /usr/lib/gnupg/scdaemon.exe
gnupg /usr/share/
gnupg /usr/share/doc/
gnupg /usr/share/doc/gnupg/
gnupg /usr/share/doc/gnupg/DCO
gnupg /usr/share/doc/gnupg/DETAILS
gnupg /usr/share/doc/gnupg/examples/
gnupg /usr/share/doc/gnupg/examples/Automatic.prf
gnupg /usr/share/doc/gnupg/examples/debug.prf
gnupg /usr/share/doc/gnupg/examples/gpgconf.conf
gnupg /usr/share/doc/gnupg/examples/pwpattern.list
gnupg /usr/share/doc/gnupg/examples/README
gnupg /usr/share/doc/gnupg/examples/scd-event
gnupg /usr/share/doc/gnupg/examples/systemd-user/
gnupg /usr/share/doc/gnupg/examples/systemd-user/dirmngr.service
gnupg /usr/share/doc/gnupg/examples/systemd-user/dirmngr.socket
gnupg /usr/share/doc/gnupg/examples/systemd-user/gpg-agent-browser.socket
gnupg /usr/share/doc/gnupg/examples/systemd-user/gpg-agent-extra.socket
gnupg /usr/share/doc/gnupg/examples/systemd-user/gpg-agent-ssh.socket
gnupg /usr/share/doc/gnupg/examples/systemd-user/gpg-agent.service
gnupg /usr/share/doc/gnupg/examples/systemd-user/gpg-agent.socket
gnupg /usr/share/doc/gnupg/examples/systemd-user/README
gnupg /usr/share/doc/gnupg/examples/trustlist.txt
gnupg /usr/share/doc/gnupg/examples/VS-NfD.prf
gnupg /usr/share/doc/gnupg/FAQ
gnupg /usr/share/doc/gnupg/HACKING
gnupg /usr/share/doc/gnupg/KEYSERVER
gnupg /usr/share/doc/gnupg/OpenPGP
gnupg /usr/share/doc/gnupg/README
gnupg /usr/share/doc/gnupg/TRANSLATE
gnupg /usr/share/gnupg/
gnupg /usr/share/gnupg/distsigkey.gpg
gnupg /usr/share/gnupg/help.be.txt
gnupg /usr/share/gnupg/help.ca.txt
gnupg /usr/share/gnupg/help.cs.txt
gnupg /usr/share/gnupg/help.da.txt
gnupg /usr/share/gnupg/help.de.txt
gnupg /usr/share/gnupg/help.el.txt
gnupg /usr/share/gnupg/help.eo.txt
gnupg /usr/share/gnupg/help.es.txt
gnupg /usr/share/gnupg/help.et.txt
gnupg /usr/share/gnupg/help.fi.txt
gnupg /usr/share/gnupg/help.fr.txt
gnupg /usr/share/gnupg/help.gl.txt
gnupg /usr/share/gnupg/help.hu.txt
gnupg /usr/share/gnupg/help.id.txt
gnupg /usr/share/gnupg/help.it.txt
gnupg /usr/share/gnupg/help.ja.txt
gnupg /usr/share/gnupg/help.nb.txt
gnupg /usr/share/gnupg/help.pl.txt
gnupg /usr/share/gnupg/help.pt.txt
gnupg /usr/share/gnupg/help.pt_BR.txt
gnupg /usr/share/gnupg/help.ro.txt
gnupg /usr/share/gnupg/help.ru.txt
gnupg /usr/share/gnupg/help.sk.txt
gnupg /usr/share/gnupg/help.sv.txt
gnupg /usr/share/gnupg/help.tr.txt
gnupg /usr/share/gnupg/help.txt
gnupg /usr/share/gnupg/help.zh_CN.txt
gnupg /usr/share/gnupg/help.zh_TW.txt
gnupg /usr/share/gnupg/sks-keyservers.netCA.pem
gnupg /usr/share/info/
gnupg /usr/share/info/gnupg.info-1.gz
gnupg /usr/share/info/gnupg.info-2.gz
gnupg /usr/share/info/gnupg.info.gz
gnupg /usr/share/locale/
gnupg /usr/share/locale/ca/
gnupg /usr/share/locale/ca/LC_MESSAGES/
gnupg /usr/share/locale/ca/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/cs/
gnupg /usr/share/locale/cs/LC_MESSAGES/
gnupg /usr/share/locale/cs/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/da/
gnupg /usr/share/locale/da/LC_MESSAGES/
gnupg /usr/share/locale/da/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/de/
gnupg /usr/share/locale/de/LC_MESSAGES/
gnupg /usr/share/locale/de/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/el/
gnupg /usr/share/locale/el/LC_MESSAGES/
gnupg /usr/share/locale/el/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/en@boldquot/
gnupg /usr/share/locale/en@boldquot/LC_MESSAGES/
gnupg /usr/share/locale/en@boldquot/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/en@quot/
gnupg /usr/share/locale/en@quot/LC_MESSAGES/
gnupg /usr/share/locale/en@quot/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/eo/
gnupg /usr/share/locale/eo/LC_MESSAGES/
gnupg /usr/share/locale/eo/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/es/
gnupg /usr/share/locale/es/LC_MESSAGES/
gnupg /usr/share/locale/es/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/et/
gnupg /usr/share/locale/et/LC_MESSAGES/
gnupg /usr/share/locale/et/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/fi/
gnupg /usr/share/locale/fi/LC_MESSAGES/
gnupg /usr/share/locale/fi/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/fr/
gnupg /usr/share/locale/fr/LC_MESSAGES/
gnupg /usr/share/locale/fr/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/gl/
gnupg /usr/share/locale/gl/LC_MESSAGES/
gnupg /usr/share/locale/gl/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/hu/
gnupg /usr/share/locale/hu/LC_MESSAGES/
gnupg /usr/share/locale/hu/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/id/
gnupg /usr/share/locale/id/LC_MESSAGES/
gnupg /usr/share/locale/id/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/it/
gnupg /usr/share/locale/it/LC_MESSAGES/
gnupg /usr/share/locale/it/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/ja/
gnupg /usr/share/locale/ja/LC_MESSAGES/
gnupg /usr/share/locale/ja/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/nb/
gnupg /usr/share/locale/nb/LC_MESSAGES/
gnupg /usr/share/locale/nb/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/pl/
gnupg /usr/share/locale/pl/LC_MESSAGES/
gnupg /usr/share/locale/pl/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/pt/
gnupg /usr/share/locale/pt/LC_MESSAGES/
gnupg /usr/share/locale/pt/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/ro/
gnupg /usr/share/locale/ro/LC_MESSAGES/
gnupg /usr/share/locale/ro/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/ru/
gnupg /usr/share/locale/ru/LC_MESSAGES/
gnupg /usr/share/locale/ru/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/sk/
gnupg /usr/share/locale/sk/LC_MESSAGES/
gnupg /usr/share/locale/sk/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/sv/
gnupg /usr/share/locale/sv/LC_MESSAGES/
gnupg /usr/share/locale/sv/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/tr/
gnupg /usr/share/locale/tr/LC_MESSAGES/
gnupg /usr/share/locale/tr/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/uk/
gnupg /usr/share/locale/uk/LC_MESSAGES/
gnupg /usr/share/locale/uk/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/zh_CN/
gnupg /usr/share/locale/zh_CN/LC_MESSAGES/
gnupg /usr/share/locale/zh_CN/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/locale/zh_TW/
gnupg /usr/share/locale/zh_TW/LC_MESSAGES/
gnupg /usr/share/locale/zh_TW/LC_MESSAGES/gnupg2.mo
gnupg /usr/share/man/
gnupg /usr/share/man/man1/
gnupg /usr/share/man/man1/dirmngr-client.1.gz
gnupg /usr/share/man/man1/gpg-agent.1.gz
gnupg /usr/share/man/man1/gpg-connect-agent.1.gz
gnupg /usr/share/man/man1/gpg-preset-passphrase.1.gz
gnupg /usr/share/man/man1/gpg-wks-client.1.gz
gnupg /usr/share/man/man1/gpg-wks-server.1.gz
gnupg /usr/share/man/man1/gpg.1.gz
gnupg /usr/share/man/man1/gpgconf.1.gz
gnupg /usr/share/man/man1/gpgparsemail.1.gz
gnupg /usr/share/man/man1/gpgsm.1.gz
gnupg /usr/share/man/man1/gpgtar.1.gz
gnupg /usr/share/man/man1/gpgv.1.gz
gnupg /usr/share/man/man1/scdaemon.1.gz
gnupg /usr/share/man/man1/watchgnupg.1.gz
gnupg /usr/share/man/man7/
gnupg /usr/share/man/man7/gnupg.7.gz
gnupg /usr/share/man/man8/
gnupg /usr/share/man/man8/addgnupghome.8.gz
gnupg /usr/share/man/man8/applygnupgdefaults.8.gz
gnupg /usr/share/man/man8/dirmngr.8.gz

Interestingly the Git\usr\bin folder still contains the gpg-error.exe after selecting "external GPG"; everything else (that has gpg in its name) looks correctly removed.
Additionally, there are e.g. dirmngr-client.exe and dirmngr.exe that also get removed (as they are part of the gnupg package). I have no idea what the implications of this are.

Detection of the winget packages GnuPG.GnuPG and GnuPG.Gpg4win in the installer works fine: the GPG selection page is only shown if e.g. one of them is installed. Otherwise the installation proceeds as it always did and uses internal GPG.

@Okeanos Okeanos changed the title installer: add option for external GnuGP installer: add option for external GnuPG Feb 11, 2023
This pull request addresses git-for-windows/git/issues/3997 by adding an
additional detection mechanism for externally supplied GnuPG binaries to a new
choice page in the installer and allows the user to "skip" the installation of
the bundled GPG related binaries.

Signed-off-by: Nikolas Grottendieck <[email protected]>
@Okeanos Okeanos force-pushed the feature/external-gpg branch from e8d408d to 8451878 Compare February 11, 2023 15:42
@dscho
Copy link
Member

dscho commented Feb 22, 2023

Interestingly the Git\usr\bin folder still contains the gpg-error.exe after selecting "external GPG"; everything else (that has gpg in its name) looks correctly removed.

The solution to that riddle is:

$ pacman -Qo /usr/bin/gpg-error.exe
/usr/bin/gpg-error.exe is owned by libgpg-error 1.42-2

There should be also a left-over msys-gpg-error-0.dll:

$ pacman -Ql libgpg-error | grep -v locale
libgpg-error /usr/
libgpg-error /usr/bin/
libgpg-error /usr/bin/gpg-error.exe
libgpg-error /usr/bin/msys-gpg-error-0.dll
libgpg-error /usr/bin/yat2m.exe
libgpg-error /usr/share/

We probably need to remove the contents of that package, too. In general, it might be a bit more complicated than just listing one or two packages' contents:

$ pactree gnupg
gnupg
├─bzip2
│ └─libbz2
│   └─gcc-libs
├─libassuan
│ ├─gcc-libs
│ └─libgpg-error
│   ├─bash provides sh
│   ├─libiconv
│   │ ├─gcc-libs
│   │ └─libintl
│   │   ├─gcc-libs
│   │   └─libiconv
│   └─libintl
├─libbz2
├─libcurl
│ ├─ca-certificates
│ │ ├─bash
│ │ ├─openssl
│ │ │ ├─libopenssl
│ │ │ │ └─zlib
│ │ │ │   └─gcc-libs
│ │ │ └─zlib
│ │ ├─findutils
│ │ │ ├─libiconv
│ │ │ └─libintl
│ │ ├─coreutils
│ │ │ ├─gmp
│ │ │ ├─libiconv
│ │ │ └─libintl
│ │ ├─sed
│ │ │ ├─libintl
│ │ │ └─bash provides sh
│ │ └─p11-kit
│ │   └─libp11-kit=0.24.1
│ │     ├─libffi
│ │     ├─libintl
│ │     └─libtasn1
│ │       └─info
│ │         ├─gzip
│ │         │ ├─bash
│ │         │ └─less
│ │         │   ├─ncurses
│ │         │   │ └─gcc-libs
│ │         │   └─libpcre2_8
│ │         │     └─gcc-libs
│ │         ├─libcrypt
│ │         │ └─gcc-libs
│ │         ├─libintl
│ │         └─ncurses
│ ├─heimdal-libs
│ │ ├─libcrypt
│ │ ├─libedit
│ │ │ ├─ncurses
│ │ │ └─bash provides sh
│ │ ├─libsqlite
│ │ │ ├─libreadline
│ │ │ │ └─ncurses
│ │ │ ├─zlib
│ │ │ └─tcl
│ │ │   └─zlib
│ │ └─libopenssl
│ ├─libcrypt
│ ├─libidn2
│ │ ├─libunistring
│ │ │ └─libiconv
│ │ └─libintl
│ ├─libnghttp2
│ │ └─gcc-libs
│ ├─libpsl
│ │ ├─libxslt
│ │ │ ├─libxml2
│ │ │ │ ├─coreutils
│ │ │ │ ├─liblzma
│ │ │ │ │ ├─bash provides sh
│ │ │ │ │ ├─libiconv
│ │ │ │ │ └─gettext
│ │ │ │ │   ├─libintl
│ │ │ │ │   ├─libgettextpo
│ │ │ │ │   │ └─gcc-libs
│ │ │ │ │   └─libasprintf
│ │ │ │ │     └─gcc-libs
│ │ │ │ ├─libreadline
│ │ │ │ └─zlib
│ │ │ └─libgcrypt
│ │ │   └─libgpg-error
│ │ ├─libidn2
│ │ └─libunistring
│ ├─libssh2
│ │ ├─ca-certificates
│ │ ├─openssl
│ │ └─zlib
│ ├─openssl
│ └─zlib
├─libgcrypt
├─libgpg-error
├─libgnutls
│ ├─gcc-libs
│ ├─libidn2
│ ├─libiconv
│ ├─libintl
│ ├─gmp
│ ├─libnettle
│ │ └─libhogweed
│ │   └─gmp
│ ├─libp11-kit
│ ├─libtasn1
│ └─zlib
├─libiconv
├─libintl
├─libksba
│ ├─gcc-libs
│ └─libgpg-error
├─libnpth
│ └─gcc-libs
├─libreadline
├─libsqlite
├─nettle
│ └─libnettle
├─pinentry
│ ├─ncurses
│ ├─libassuan
│ └─libgpg-error
└─zlib

Some of these are shared with other dependencees, e.g. libreadline, and should not be removed together with gpg.exe:

$ pactree -r libreadline | grep awk
├─gawk

But others do need to be removed, too, e.g. pinentry:

$ pactree -r pinentry
pinentry
└─gnupg
  ├─libgpgme
  └─pacman
    ├─pacman-contrib
    └─pkgfile

I have to admit that I am not completely certain how best to handle this.

One option might be to modify make-file-list.sh to optionally skip gnupg and then run it once with, and once without that option and list the files in the difference set. Something like this:

diff --git a/make-file-list.sh b/make-file-list.sh
index 9960b4809..39d305994 100755
--- a/make-file-list.sh
+++ b/make-file-list.sh
@@ -166,10 +166,11 @@ mingw-w64-$PACMAN_ARCH-git-extra openssh $UTIL_PACKAGES"
 if test -z "$MINIMAL_GIT"
 then
 	packages="$packages mingw-w64-$PACMAN_ARCH-git-doc-html ncurses mintty vim nano
-		winpty less gnupg tar diffutils patch dos2unix which subversion perl-JSON
+		winpty less tar diffutils patch dos2unix which subversion perl-JSON
 		mingw-w64-$PACMAN_ARCH-tk mingw-w64-$PACMAN_ARCH-connect git-flow docx2txt
 		mingw-w64-$PACMAN_ARCH-antiword mingw-w64-$PACMAN_ARCH-odt2txt ssh-pageant
 		mingw-w64-$PACMAN_ARCH-git-lfs mingw-w64-$PACMAN_ARCH-xz tig $GIT_UPDATE_EXTRA_PACKAGES"
+	test -n "$SKIP_GNUPG" || packages="$packages gnupg"
 fi
 pacman_list $packages "$@" |
 

combined with this call:

comm -23 <(ARCH=x86_64 ./make-file-list.sh | sort) <(SKIP_GNUPG=1 ARCH=x86_64 ./make-file-list.sh | sort)

But that means that we run make-file-list.sh three times now instead of a single time, and that script is not exactly quick.

Plus: That would miss libgpg-error's files because libgpg-error is a transitive dependency of curl which in turn is a transitive dependency of git-flow. And while we exclude curl explicitly, we cannot do the same for libgpg-error because in the default case it is a dependency of gnupg and therefore must be included.

Tricky business.

Additionally, there are e.g. dirmngr-client.exe and dirmngr.exe that also get removed (as they are part of the gnupg package). I have no idea what the implications of this are.

Those are long-running services (but not Windows Services, more like Unix daemons) that are used only by GnuPG. So yes, it is good that they're being removed together with gpg.exe.

@Okeanos
Copy link
Contributor Author

Okeanos commented Feb 22, 2023

Thanks for the in depth review and suggestions on how to proceed – I'll have a look in a while. Currently a little swamped with everything.

@dscho
Copy link
Member

dscho commented Feb 23, 2023

Currently a little swamped with everything.

@Okeanos that's exactly the same reason why it took me so long to get to review your PR, sorry!

@Okeanos
Copy link
Contributor Author

Okeanos commented Apr 1, 2023

Just as a reminder (also to myself) I am still willing to work on this (unless somebody would like to do the honors instead). However, I am not sure I have the mental fortitude to deal with this for a while yet. It's a non-trivial problem and I would like to give it an earnest effort in thinking through a potential solution.

If anything changes substantially with the existing scripts (i.e. causes merge conflicts) I'll likely update the PR "as-is" to be at least in a state that can be build upon.

@dscho
Copy link
Member

dscho commented May 2, 2023

An easier-to-achieve alternative comes to mind: instead of deleting gpg.exe and all its dependent files (modulo those that are needed by other executables), we could simply set gpg.program accordingly. @Okeanos thoughts?

@Okeanos
Copy link
Contributor Author

Okeanos commented May 2, 2023

@dscho that sounds similar to what happened with the original SSH setup stuff: it only works for git specifically but other programs may want to use the same GPG executable correctly as well and obviously will use it as found on $PATH.

The $PATH stuff and doing magic to that instead had a separate discussion as well. Not sure whether we can/or want to revisit that?

I'll mull it over some more and hope I have time to actively work on this soon™ again.

@dscho
Copy link
Member

dscho commented May 2, 2023

Fair enough.

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.

2 participants