summaryrefslogtreecommitdiff
path: root/lib/spack/spack/fetch_strategy.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/spack/spack/fetch_strategy.py')
-rw-r--r--lib/spack/spack/fetch_strategy.py87
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: