wrap: Use MESON_PACKAGE_CACHE_DIR as default packagecache path

Allow packagecache to contain already extracted directory to match what
some distro does with Cargo source packages in /usr/share/cargo/registry.

Note that there is no need to lock the cache directory because we
download into a temporary name and atomically rename afterward. It means
we could be downloading the same file twice, but at least integrity is
guaranteed.

Fixes: #12211
pull/11946/merge
Xavier Claessens 2 years ago committed by Nirbheek Chauhan
parent f07476a896
commit fe9af72684
  1. 6
      docs/markdown/Wrap-dependency-system-manual.md
  2. 7
      docs/markdown/snippets/meson_home.md
  3. 14
      mesonbuild/wrap/wrap.py
  4. 1
      test cases/unit/116 meson package cache dir/cache_dir/bar/meson.build
  5. BIN
      test cases/unit/116 meson package cache dir/cache_dir/foo.zip
  6. 4
      test cases/unit/116 meson package cache dir/meson.build
  7. 3
      test cases/unit/116 meson package cache dir/subprojects/bar.wrap
  8. 5
      test cases/unit/116 meson package cache dir/subprojects/foo.wrap
  9. 10
      unittests/platformagnostictests.py

@ -109,6 +109,12 @@ project's `subprojects/packagecache` directory, it will be used instead
of downloading the file, even if `--wrap-mode` option is set to of downloading the file, even if `--wrap-mode` option is set to
`nodownload`. The file's hash will be checked. `nodownload`. The file's hash will be checked.
Since *1.3.0* if the `MESON_PACKAGE_CACHE_DIR` environment variable is set, it is used instead of
the project's `subprojects/packagecache`. This allows sharing the cache across multiple
projects. In addition it can contain an already extracted source tree as long as it
has the same directory name as the `directory` field in the wrap file. In that
case, the directory will be copied into `subprojects/` before applying patches.
### Specific to VCS-based wraps ### Specific to VCS-based wraps
- `url` - name of the wrap-git repository to clone. Required. - `url` - name of the wrap-git repository to clone. Required.
- `revision` - name of the revision to checkout. Must be either: a - `revision` - name of the revision to checkout. Must be either: a

@ -0,0 +1,7 @@
## New environment variable `MESON_PACKAGE_CACHE_DIR`
If the `MESON_PACKAGE_CACHE_DIR` environment variable is set, it is used instead of the
project's `subprojects/packagecache`. This allows sharing the cache across multiple
projects. In addition it can contain an already extracted source tree as long as it
has the same directory name as the `directory` field in the wrap file. In that
case, the directory will be copied into `subprojects/` before applying patches.

@ -289,7 +289,7 @@ class Resolver:
def __post_init__(self) -> None: def __post_init__(self) -> None:
self.subdir_root = os.path.join(self.source_dir, self.subdir) self.subdir_root = os.path.join(self.source_dir, self.subdir)
self.cachedir = os.path.join(self.subdir_root, 'packagecache') self.cachedir = os.environ.get('MESON_PACKAGE_CACHE_DIR') or os.path.join(self.subdir_root, 'packagecache')
self.wraps: T.Dict[str, PackageDefinition] = {} self.wraps: T.Dict[str, PackageDefinition] = {}
self.netrc: T.Optional[netrc] = None self.netrc: T.Optional[netrc] = None
self.provided_deps: T.Dict[str, PackageDefinition] = {} self.provided_deps: T.Dict[str, PackageDefinition] = {}
@ -462,7 +462,17 @@ class Resolver:
if not os.path.isdir(self.dirname): if not os.path.isdir(self.dirname):
raise WrapException('Path already exists but is not a directory') raise WrapException('Path already exists but is not a directory')
else: else:
if self.wrap.type == 'file': # Check first if we have the extracted directory in our cache. This can
# happen for example when MESON_PACKAGE_CACHE_DIR=/usr/share/cargo/registry
# on distros that ships Rust source code.
# TODO: We don't currently clone git repositories into the cache
# directory, but we should to avoid cloning multiple times the same
# repository. In that case, we could do something smarter than
# copy_tree() here.
cached_directory = os.path.join(self.cachedir, self.directory)
if os.path.isdir(cached_directory):
self.copy_tree(cached_directory, self.dirname)
elif self.wrap.type == 'file':
self.get_file() self.get_file()
else: else:
self.check_can_download() self.check_can_download()

@ -0,0 +1,4 @@
project('meson package cache dir')
subproject('foo')
subproject('bar')

@ -0,0 +1,5 @@
[wrap-file]
directory = foo
source_url = http://server.invalid/foo.zip
source_filename = foo.zip
source_hash = c5dd7e8fca93045f736c83700686722b0fbc20b7dc4597b295060684c5b05b72

@ -18,6 +18,7 @@ import pickle
import tempfile import tempfile
import subprocess import subprocess
import textwrap import textwrap
import shutil
from unittest import skipIf, SkipTest from unittest import skipIf, SkipTest
from pathlib import Path from pathlib import Path
@ -261,3 +262,12 @@ class PlatformAgnosticTests(BasePlatformTests):
self.assertEqual(data['modules'], expected) self.assertEqual(data['modules'], expected)
self.assertEqual(data['count'], 68) self.assertEqual(data['count'], 68)
def test_meson_package_cache_dir(self):
# Copy testdir into temporary directory to not pollute meson source tree.
testdir = os.path.join(self.unit_test_dir, '116 meson package cache dir')
srcdir = os.path.join(self.builddir, 'srctree')
shutil.copytree(testdir, srcdir)
builddir = os.path.join(srcdir, '_build')
self.change_builddir(builddir)
self.init(srcdir, override_envvars={'MESON_PACKAGE_CACHE_DIR': os.path.join(srcdir, 'cache_dir')})

Loading…
Cancel
Save