Default BINPKG_COMPRESSION to zstd (bug 715108)

This includes a _compat_upgrade.binpkg_compression script that the
ebuild can call in pkg_preinst in order to maintain a backward-compatible
bzip2 default when appropriate, ensuring that binary package consumers
are not caught off guard.

Bug: https://bugs.gentoo.org/715108
Reviewed-by: Brian Dolbec <dolsen@gentoo.org>
Signed-off-by: Zac Medico <zmedico@gentoo.org>
diff --git a/.travis.yml b/.travis.yml
index 9269d40..2132c8c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,3 +1,4 @@
+dist: bionic
 language: python
 python:
     - 2.7
@@ -8,6 +9,9 @@
     - pypy3
 
 # command to install dependencies
+before_install:
+    # Use "dist: bionic" to get a zstd with --long support.
+    - sudo apt-get -y install zstd
 install:
     - pip install tox
 
diff --git a/cnf/make.globals b/cnf/make.globals
index 4a59dbe..dd3f28f 100644
--- a/cnf/make.globals
+++ b/cnf/make.globals
@@ -34,8 +34,9 @@
 # Temporary build directory
 PORTAGE_TMPDIR="/var/tmp"
 
-# The compression used for binary packages. Defaults to zstd when USE=zstd is enabled.
-BINPKG_COMPRESS="bzip2"
+# The compression used for binary packages. Defaults to zstd except for
+# existing installs where bzip2 is used for backward compatibility.
+BINPKG_COMPRESS="zstd"
 
 # Fetching command (3 tries, passive ftp for firewall compatibility)
 FETCHCOMMAND="wget -t 3 -T 60 --passive-ftp -O \"\${DISTDIR}/\${FILE}\" \"\${URI}\""
diff --git a/lib/portage/_compat_upgrade/binpkg_compression.py b/lib/portage/_compat_upgrade/binpkg_compression.py
new file mode 100644
index 0000000..0f57047
--- /dev/null
+++ b/lib/portage/_compat_upgrade/binpkg_compression.py
@@ -0,0 +1,40 @@
+# Copyright 2020 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+import re
+
+import portage
+from portage import os
+from portage.const import GLOBAL_CONFIG_PATH
+
+COMPAT_BINPKG_COMPRESS = 'bzip2'
+
+
+def main():
+	"""
+	If the current installation is still configured to use the old
+	default BINPKG_COMPRESS=bzip2 setting, then patch make.globals
+	inside ${ED} to maintain backward compatibility, ensuring that
+	binary package consumers are not caught off guard. This is
+	intended to be called from the ebuild as follows:
+
+	pkg_preinst() {
+		python_setup
+		env -u BINPKG_COMPRESS
+			PYTHONPATH="${D%/}$(python_get_sitedir)${PYTHONPATH:+:${PYTHONPATH}}" \
+			"${PYTHON}" -m portage._compat_upgrade.binpkg_compression || die
+	}
+	"""
+	if portage.settings.get('BINPKG_COMPRESS', COMPAT_BINPKG_COMPRESS) == COMPAT_BINPKG_COMPRESS:
+		config_path = os.path.join(os.environ['ED'], GLOBAL_CONFIG_PATH.lstrip(os.sep), 'make.globals')
+		with open(config_path) as f:
+			content = f.read()
+			compat_setting = 'BINPKG_COMPRESS="{}"'.format(COMPAT_BINPKG_COMPRESS)
+			portage.output.EOutput().einfo('Setting make.globals default {} for backward compatibility'.format(compat_setting))
+			content = re.sub('^BINPKG_COMPRESS=.*$', compat_setting, content, flags=re.MULTILINE)
+		with open(config_path, 'wt') as f:
+			f.write(content)
+
+
+if __name__ == '__main__':
+	main()
diff --git a/lib/portage/tests/resolver/ResolverPlayground.py b/lib/portage/tests/resolver/ResolverPlayground.py
index 98831e0..de80a0c 100644
--- a/lib/portage/tests/resolver/ResolverPlayground.py
+++ b/lib/portage/tests/resolver/ResolverPlayground.py
@@ -112,6 +112,7 @@
 				"uname",
 				"uniq",
 				"xargs",
+				"zstd",
 			)
 			# Exclude internal wrappers from PATH lookup.
 			orig_path = os.environ['PATH']
diff --git a/man/make.conf.5 b/man/make.conf.5
index f82fed6..a3bd662 100644
--- a/man/make.conf.5
+++ b/man/make.conf.5
@@ -1,4 +1,4 @@
-.TH "MAKE.CONF" "5" "Nov 2019" "Portage VERSION" "Portage"
+.TH "MAKE.CONF" "5" "May 2020" "Portage VERSION" "Portage"
 .SH "NAME"
 make.conf \- custom settings for Portage
 .SH "SYNOPSIS"
@@ -115,7 +115,7 @@
 packages\fR. Supported settings and compression algorithms are: bzip2, gzip,
 lz4, lzip, lzop, xz, zstd.
 .br
-Defaults to "bzip2".
+Defaults to "zstd".
 .br
 .I Example:
 .nf