diff options
Diffstat (limited to 'lib/spack/spack/fetch_strategy.py')
-rw-r--r-- | lib/spack/spack/fetch_strategy.py | 87 |
1 files changed, 61 insertions, 26 deletions
diff --git a/lib/spack/spack/fetch_strategy.py b/lib/spack/spack/fetch_strategy.py index 136d786e3f..6db41e2328 100644 --- a/lib/spack/spack/fetch_strategy.py +++ b/lib/spack/spack/fetch_strategy.py @@ -49,10 +49,10 @@ import spack.util.crypto as crypto import spack.util.pattern as pattern import spack.util.url as url_util import spack.util.web as web_util +import spack.version from spack.util.compression import decompressor_for, extension from spack.util.executable import CommandNotFoundError, which from spack.util.string import comma_and, quote -from spack.version import Version, ver #: List of all fetch strategies, created by FetchStrategy metaclass. all_strategies = [] @@ -750,7 +750,7 @@ class GoFetchStrategy(VCSFetchStrategy): @property def go_version(self): vstring = self.go('version', output=str).split(' ')[2] - return Version(vstring) + return spack.version.Version(vstring) @property def go(self): @@ -843,7 +843,7 @@ class GitFetchStrategy(VCSFetchStrategy): """ version_output = git_exe('--version', output=str) m = re.search(GitFetchStrategy.git_version_re, version_output) - return Version(m.group(1)) + return spack.version.Version(m.group(1)) @property def git(self): @@ -852,7 +852,7 @@ class GitFetchStrategy(VCSFetchStrategy): # Disable advice for a quieter fetch # https://github.com/git/git/blob/master/Documentation/RelNotes/1.7.2.txt - if self.git_version >= Version('1.7.2'): + if self.git_version >= spack.version.Version('1.7.2'): self._git.add_default_arg('-c') self._git.add_default_arg('advice.detachedHead=false') @@ -895,25 +895,52 @@ class GitFetchStrategy(VCSFetchStrategy): tty.debug('Already fetched {0}'.format(self.stage.source_path)) return + self.clone(commit=self.commit, branch=self.branch, tag=self.tag) + + def clone(self, dest=None, commit=None, branch=None, tag=None, bare=False): + """ + Clone a repository to a path. + + This method handles cloning from git, but does not require a stage. + + Arguments: + dest (str or None): The path into which the code is cloned. If None, + requires a stage and uses the stage's source path. + commit (str or None): A commit to fetch from the remote. Only one of + commit, branch, and tag may be non-None. + branch (str or None): A branch to fetch from the remote. + tag (str or None): A tag to fetch from the remote. + bare (bool): Execute a "bare" git clone (--bare option to git) + """ + # Default to spack source path + dest = dest or self.stage.source_path tty.debug('Cloning git repository: {0}'.format(self._repo_info())) git = self.git - if self.commit: + debug = spack.config.get('config:debug') + + if bare: + # We don't need to worry about which commit/branch/tag is checked out + clone_args = ['clone', '--bare'] + if not debug: + clone_args.append('--quiet') + clone_args.extend([self.url, dest]) + git(*clone_args) + elif commit: # Need to do a regular clone and check out everything if # they asked for a particular commit. - debug = spack.config.get('config:debug') - clone_args = ['clone', self.url] if not debug: clone_args.insert(1, '--quiet') with temp_cwd(): git(*clone_args) repo_name = get_single_file('.') - self.stage.srcdir = repo_name - shutil.move(repo_name, self.stage.source_path) + if self.stage: + self.stage.srcdir = repo_name + shutil.move(repo_name, dest) - with working_dir(self.stage.source_path): - checkout_args = ['checkout', self.commit] + with working_dir(dest): + checkout_args = ['checkout', commit] if not debug: checkout_args.insert(1, '--quiet') git(*checkout_args) @@ -921,18 +948,18 @@ class GitFetchStrategy(VCSFetchStrategy): else: # Can be more efficient if not checking out a specific commit. args = ['clone'] - if not spack.config.get('config:debug'): + if not debug: args.append('--quiet') # If we want a particular branch ask for it. - if self.branch: - args.extend(['--branch', self.branch]) - elif self.tag and self.git_version >= ver('1.8.5.2'): - args.extend(['--branch', self.tag]) + if branch: + args.extend(['--branch', branch]) + elif tag and self.git_version >= spack.version.ver('1.8.5.2'): + args.extend(['--branch', tag]) # Try to be efficient if we're using a new enough git. # This checks out only one branch's history - if self.git_version >= ver('1.7.10'): + if self.git_version >= spack.version.ver('1.7.10'): if self.get_full_repo: args.append('--no-single-branch') else: @@ -942,7 +969,7 @@ class GitFetchStrategy(VCSFetchStrategy): # Yet more efficiency: only download a 1-commit deep # tree, if the in-use git and protocol permit it. if (not self.get_full_repo) and \ - self.git_version >= ver('1.7.1') and \ + self.git_version >= spack.version.ver('1.7.1') and \ self.protocol_supports_shallow_clone(): args.extend(['--depth', '1']) @@ -950,14 +977,15 @@ class GitFetchStrategy(VCSFetchStrategy): git(*args) repo_name = get_single_file('.') - self.stage.srcdir = repo_name - shutil.move(repo_name, self.stage.source_path) + if self.stage: + self.stage.srcdir = repo_name + shutil.move(repo_name, dest) - with working_dir(self.stage.source_path): + with working_dir(dest): # For tags, be conservative and check them out AFTER # cloning. Later git versions can do this with clone # --branch, but older ones fail. - if self.tag and self.git_version < ver('1.8.5.2'): + if tag and self.git_version < spack.version.ver('1.8.5.2'): # pull --tags returns a "special" error code of 1 in # older versions that we have to ignore. # see: https://github.com/git/git/commit/19d122b @@ -971,7 +999,7 @@ class GitFetchStrategy(VCSFetchStrategy): git(*co_args) if self.submodules_delete: - with working_dir(self.stage.source_path): + with working_dir(dest): for submodule_to_delete in self.submodules_delete: args = ['rm', submodule_to_delete] if not spack.config.get('config:debug'): @@ -980,7 +1008,7 @@ class GitFetchStrategy(VCSFetchStrategy): # Init submodules if the user asked for them. if self.submodules: - with working_dir(self.stage.source_path): + with working_dir(dest): args = ['submodule', 'update', '--init', '--recursive'] if not spack.config.get('config:debug'): args.insert(1, '--quiet') @@ -1502,8 +1530,15 @@ def for_package_version(pkg, version): check_pkg_attributes(pkg) - if not isinstance(version, Version): - version = Version(version) + if not isinstance(version, spack.version.Version): + version = spack.version.Version(version) + + # if it's a commit, we must use a GitFetchStrategy + if version.is_commit and hasattr(pkg, "git"): + # Populate the version with comparisons to other commits + version.generate_commit_lookup(pkg) + fetcher = GitFetchStrategy(git=pkg.git, commit=str(version)) + return fetcher # If it's not a known version, try to extrapolate one by URL if version not in pkg.versions: |