diff options
author | Nirbheek Chauhan <nirbheek@centricular.com> | 2017-03-25 04:03:03 +0530 |
---|---|---|
committer | Nirbheek Chauhan <nirbheek@centricular.com> | 2017-03-25 06:47:04 +0530 |
commit | a60d688973e8903015f6e4b157332c5c98562f55 (patch) | |
tree | 1fdc8b108bc5af9944d81571f0b8dc8dd053f571 | |
parent | fb809e79e55160e519be6bafc222c6ba00573793 (diff) | |
download | meson-a60d688973e8903015f6e4b157332c5c98562f55.zip meson-a60d688973e8903015f6e4b157332c5c98562f55.tar.gz meson-a60d688973e8903015f6e4b157332c5c98562f55.tar.bz2 |
wrap: Initialize subprojects that are git submodules
This will benefit projects such as GNOME Recipes that prefer using
submodules over wraps because it's easier to maintain since git is
aware of it, and because it integrates with their existing
workflow. Without this, these projects have to manually initialize
the submodules which is completely unnecessary.
Closes https://github.com/mesonbuild/meson/issues/1449
-rw-r--r-- | mesonbuild/interpreter.py | 12 | ||||
-rw-r--r-- | mesonbuild/wrap/wrap.py | 50 |
2 files changed, 50 insertions, 12 deletions
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 79a531d..f9c1579 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1498,11 +1498,13 @@ class Interpreter(InterpreterBase): raise InvalidCode('Recursive include of subprojects: %s.' % incpath) if dirname in self.subprojects: return self.subprojects[dirname] - r = wrap.Resolver(os.path.join(self.build.environment.get_source_dir(), self.subproject_dir)) - resolved = r.resolve(dirname) - if resolved is None: - msg = 'Subproject directory {!r} does not exist and cannot be downloaded.' - raise InterpreterException(msg.format(os.path.join(self.subproject_dir, dirname))) + subproject_dir_abs = os.path.join(self.environment.get_source_dir(), self.subproject_dir) + r = wrap.Resolver(subproject_dir_abs) + try: + resolved = r.resolve(dirname) + except RuntimeError as e: + msg = 'Subproject directory {!r} does not exist and cannot be downloaded:\n{}' + raise InterpreterException(msg.format(os.path.join(self.subproject_dir, dirname), e)) subdir = os.path.join(self.subproject_dir, resolved) os.makedirs(os.path.join(self.build.environment.get_build_dir(), subdir), exist_ok=True) self.args_frozen = True diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index 05d255d..ad2e3e4 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -37,6 +37,13 @@ def build_ssl_context(): ctx.load_default_certs() return ctx +def quiet_git(cmd): + pc = subprocess.Popen(['git'] + cmd, stdout=subprocess.PIPE) + out, err = pc.communicate() + if pc.returncode != 0: + return False, err + return True, out + def open_wrapdburl(urlstring): global ssl_warning_printed if has_ssl: @@ -94,24 +101,31 @@ class Resolver: def resolve(self, packagename): # Check if the directory is already resolved dirname = Path(os.path.join(self.subdir_root, packagename)) + subprojdir = os.path.join(*dirname.parts[-2:]) if dirname.is_dir(): if (dirname / 'meson.build').is_file(): # The directory is there and has meson.build? Great, use it. return packagename - # Is the dir not empty and also not a git submodule dir that is - # not checkout properly? Can't do anything, exception! + # Is the dir not empty and also not a git submodule dir that is + # not checkout properly? Can't do anything, exception! elif next(dirname.iterdir(), None) and not (dirname / '.git').is_file(): m = '{!r} is not empty and has no meson.build files' - raise RuntimeError(m.format(dirname)) + raise RuntimeError(m.format(subprojdir)) elif dirname.exists(): - m = '{!r} is not a directory, can not use as subproject' - raise RuntimeError(m.format(dirname)) + m = '{!r} already exists and is not a dir; cannot use as subproject' + raise RuntimeError(m.format(subprojdir)) + + dirname = str(dirname) + # Check if the subproject is a git submodule + if self.resolve_git_submodule(dirname): + return packagename # Check if there's a .wrap file for this subproject fname = os.path.join(self.subdir_root, packagename + '.wrap') if not os.path.isfile(fname): # No wrap file with this name? Give up. - return None + m = 'No {}.wrap found for {!r}' + raise RuntimeError(m.format(packagename, subprojdir)) p = PackageDefinition(fname) if p.type == 'file': if not os.path.isdir(self.cachedir): @@ -123,9 +137,31 @@ class Resolver: elif p.type == "hg": self.get_hg(p) else: - raise RuntimeError('Unreachable code.') + raise AssertionError('Unreachable code.') return p.get('directory') + def resolve_git_submodule(self, dirname): + # Are we in a git repository? + ret, out = quiet_git(['rev-parse']) + if not ret: + return False + # Is `dirname` a submodule? + ret, out = quiet_git(['submodule', 'status', dirname]) + if not ret: + return False + # Submodule has not been added, add it + if out.startswith(b'-'): + if subprocess.call(['git', 'submodule', 'update', dirname]) != 0: + return False + # Submodule was added already, but it wasn't populated. Do a checkout. + elif out.startswith(b' '): + if subprocess.call(['git', 'checkout', '.'], cwd=dirname): + return True + else: + m = 'Unknown git submodule output: {!r}' + raise AssertionError(m.format(out)) + return True + def get_git(self, p): checkoutdir = os.path.join(self.subdir_root, p.get('directory')) revno = p.get('revision') |