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
`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
- `url` - name of the wrap-git repository to clone. Required.
- `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:
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.netrc: T.Optional[netrc] = None
self.provided_deps: T.Dict[str, PackageDefinition] = {}
@ -462,7 +462,17 @@ class Resolver:
if not os.path.isdir(self.dirname):
raise WrapException('Path already exists but is not a directory')
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()
else:
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 subprocess
import textwrap
import shutil
from unittest import skipIf, SkipTest
from pathlib import Path
@ -261,3 +262,12 @@ class PlatformAgnosticTests(BasePlatformTests):
self.assertEqual(data['modules'], expected)
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