diff --git a/reframe/core/pipeline.py b/reframe/core/pipeline.py index 1ced2d6a1..a6e5e72a2 100644 --- a/reframe/core/pipeline.py +++ b/reframe/core/pipeline.py @@ -413,7 +413,7 @@ def pipeline_hooks(cls): #: .. versionchanged:: 3.0 #: Default value is now conditionally set to either ``'src'`` or #: :class:`None`. - sourcesdir = variable(str, type(None), value='src') + sourcesdir = variable(str, typ.Dict, type(None), value='src') #: .. versionadded:: 2.14 #: @@ -1949,11 +1949,12 @@ def _copy_to_stagedir(self, path): else: self._mark_stagedir() - def _clone_to_stagedir(self, url): + def _clone_to_stagedir(self, url, files=None): self.logger.debug(f'Cloning URL {url} into stage directory') osext.git_clone( - self.sourcesdir, self._stagedir, - timeout=rt.runtime().get_option('general/0/git_timeout') + url, self._stagedir, + timeout=rt.runtime().get_option('general/0/git_timeout'), + files=files ) self._mark_stagedir() @@ -1983,7 +1984,7 @@ def compile(self): try: commonpath = os.path.commonpath([self.sourcesdir, self.sourcepath]) - except ValueError: + except (ValueError, TypeError): commonpath = None if commonpath: @@ -1994,11 +1995,26 @@ def compile(self): ) if self._requires_stagedir_contents(): - if osext.is_url(self.sourcesdir): - self._clone_to_stagedir(self.sourcesdir) + srcdir = self.sourcesdir + if isinstance(srcdir, dict): + if 'url' not in srcdir: + raise ReframeError(f'{srcdir} misses the url key') + + url = srcdir['url'] + if not osext.is_url(url): + raise ReframeError(f'The dictionary syntax only supports ' + 'git repositories') + + self._clone_to_stagedir(url, + files=srcdir[url]['files'] if 'files' + in srcdir[url] else None, + opts=srcdir[url]['opts'] if 'opts' + in srcdir[url] else None) + elif osext.is_url(srcdir): + self._clone_to_stagedir(srcdir) else: self._copy_to_stagedir(os.path.join(self._prefix, - self.sourcesdir)) + srcdir)) # Set executable (only if hasn't been provided) if not hasattr(self, 'executable'): diff --git a/reframe/utility/osext.py b/reframe/utility/osext.py index 544c47900..bd804db66 100644 --- a/reframe/utility/osext.py +++ b/reframe/utility/osext.py @@ -692,7 +692,7 @@ def is_url(s): return parsed.scheme != '' and parsed.netloc != '' -def git_clone(url, targetdir=None, opts=None, timeout=5): +def git_clone(url, targetdir=None, opts=None, timeout=5, files=None): '''Clone a git repository from a URL. :arg url: The URL to clone from. @@ -708,7 +708,13 @@ def git_clone(url, targetdir=None, opts=None, timeout=5): targetdir = targetdir or '' opts = ' '.join(opts) if opts is not None else '' - run_command(f'git clone {opts} {url} {targetdir}', check=True) + if not files: + run_command(f'git clone {opts} {url} {targetdir}', check=True) + else: + run_command(f'git clone --no-checkout --depth=1 {opts} {url} {targetdir}', check=True) + run_command(f'git sparse-checkout set --no-cone {" ".join(files)}', check=True, cwd=targetdir) + run_command('git checkout', check=True, cwd=targetdir) + def git_repo_exists(url, timeout=5):