Add bztar support to meson dist

Some projects, like Postgres, distribute code in this format.
diff --git a/data/shell-completions/zsh/_meson b/data/shell-completions/zsh/_meson
index bd71a31..e6f50f1 100644
--- a/data/shell-completions/zsh/_meson
+++ b/data/shell-completions/zsh/_meson
@@ -32,7 +32,7 @@
 local __meson_backends="(ninja xcode ${(j. .)${:-vs{,2010,2015,2017}}})"
 local __meson_build_types="(plain debug debugoptimized minsize release)"
 local __meson_wrap_modes="(WrapMode.{default,nofallback,nodownload,forcefallback})"
-local __meson_dist_formats=("xztar" "gztar" "zip")
+local __meson_dist_formats=("xztar" "bztar" "gztar" "zip")
 local __meson_cd='-C[change into this directory before running]:target dir:_directories'
 local -a __meson_common=(
   '--prefix=[installation prefix]: :_directories'
diff --git a/docs/markdown/snippets/bztar_support.md b/docs/markdown/snippets/bztar_support.md
new file mode 100644
index 0000000..3ee4a91
--- /dev/null
+++ b/docs/markdown/snippets/bztar_support.md
@@ -0,0 +1,4 @@
+## Support for `bztar` in `meson dist`
+
+The `bztar` format is now supported in `meson dist`. This format is also known
+as `bzip2`.
diff --git a/mesonbuild/mdist.py b/mesonbuild/mdist.py
index faaf1bf..1ae0f59 100644
--- a/mesonbuild/mdist.py
+++ b/mesonbuild/mdist.py
@@ -33,9 +33,10 @@
     from ._typing import ImmutableListProtocol
     from .mesonlib import ExecutableSerialisation
 
-archive_choices = ['gztar', 'xztar', 'zip']
+archive_choices = ['bztar', 'gztar', 'xztar', 'zip']
 
-archive_extension = {'gztar': '.tar.gz',
+archive_extension = {'bztar': '.tar.bz2',
+                     'gztar': '.tar.gz',
                      'xztar': '.tar.xz',
                      'zip': '.zip'}
 
@@ -47,7 +48,7 @@
     parser.add_argument('--allow-dirty', action='store_true',
                         help='Allow even when repository contains uncommitted changes.')
     parser.add_argument('--formats', default='xztar',
-                        help='Comma separated list of archive types to create. Supports xztar (default), gztar, and zip.')
+                        help='Comma separated list of archive types to create. Supports xztar (default), bztar, gztar, and zip.')
     parser.add_argument('--include-subprojects', action='store_true',
                         help='Include source code of subprojects that have been used for the build.')
     parser.add_argument('--no-tests', action='store_true',
@@ -230,6 +231,7 @@
         os.makedirs(self.dist_sub, exist_ok=True)
         tarname = os.path.join(self.dist_sub, self.dist_name + '.tar')
         xzname = tarname + '.xz'
+        bz2name = tarname + '.bz2'
         gzname = tarname + '.gz'
         zipname = os.path.join(self.dist_sub, self.dist_name + '.zip')
         # Note that -X interprets relative paths using the current working
@@ -248,6 +250,11 @@
             with lzma.open(xzname, 'wb') as xf, open(tarname, 'rb') as tf:
                 shutil.copyfileobj(tf, xf)
             output_names.append(xzname)
+        if 'bztar' in archives:
+            import bz2
+            with bz2.open(bz2name, 'wb') as bf, open(tarname, 'rb') as tf:
+                shutil.copyfileobj(tf, bf)
+            output_names.append(bz2name)
         if 'gztar' in archives:
             with gzip.open(gzname, 'wb') as zf, open(tarname, 'rb') as tf:
                 shutil.copyfileobj(tf, zf)
diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py
index c334d9e..86ffa92 100644
--- a/unittests/allplatformstests.py
+++ b/unittests/allplatformstests.py
@@ -1505,6 +1505,8 @@
                     '''))
             xz_distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.xz')
             xz_checksumfile = xz_distfile + '.sha256sum'
+            bz_distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.bz2')
+            bz_checksumfile = bz_distfile + '.sha256sum'
             gz_distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.gz')
             gz_checksumfile = gz_distfile + '.sha256sum'
             zip_distfile = os.path.join(self.distdir, 'disttest-1.4.3.zip')
@@ -1520,10 +1522,16 @@
             self.build('dist')
             self.assertPathExists(xz_distfile)
             self.assertPathExists(xz_checksumfile)
+            self.assertPathDoesNotExist(bz_distfile)
+            self.assertPathDoesNotExist(bz_checksumfile)
             self.assertPathDoesNotExist(gz_distfile)
             self.assertPathDoesNotExist(gz_checksumfile)
             self.assertPathDoesNotExist(zip_distfile)
             self.assertPathDoesNotExist(zip_checksumfile)
+            self._run(self.meson_command + ['dist', '--formats', 'bztar'],
+                      workdir=self.builddir)
+            self.assertPathExists(bz_distfile)
+            self.assertPathExists(bz_checksumfile)
             self._run(self.meson_command + ['dist', '--formats', 'gztar'],
                       workdir=self.builddir)
             self.assertPathExists(gz_distfile)
@@ -1534,14 +1542,18 @@
             self.assertPathExists(zip_checksumfile)
             os.remove(xz_distfile)
             os.remove(xz_checksumfile)
+            os.remove(bz_distfile)
+            os.remove(bz_checksumfile)
             os.remove(gz_distfile)
             os.remove(gz_checksumfile)
             os.remove(zip_distfile)
             os.remove(zip_checksumfile)
-            self._run(self.meson_command + ['dist', '--formats', 'xztar,gztar,zip'],
+            self._run(self.meson_command + ['dist', '--formats', 'xztar,bztar,gztar,zip'],
                       workdir=self.builddir)
             self.assertPathExists(xz_distfile)
             self.assertPathExists(xz_checksumfile)
+            self.assertPathExists(bz_distfile)
+            self.assertPathExists(bz_checksumfile)
             self.assertPathExists(gz_distfile)
             self.assertPathExists(gz_checksumfile)
             self.assertPathExists(zip_distfile)