aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2017-03-25 04:03:03 +0530
committerNirbheek Chauhan <nirbheek@centricular.com>2017-03-25 06:47:04 +0530
commita60d688973e8903015f6e4b157332c5c98562f55 (patch)
tree1fdc8b108bc5af9944d81571f0b8dc8dd053f571
parentfb809e79e55160e519be6bafc222c6ba00573793 (diff)
downloadmeson-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.py12
-rw-r--r--mesonbuild/wrap/wrap.py50
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')