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
pull/1516/head
Nirbheek Chauhan 8 years ago
parent fb809e79e5
commit a60d688973
  1. 12
      mesonbuild/interpreter.py
  2. 50
      mesonbuild/wrap/wrap.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

@ -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')

Loading…
Cancel
Save