Add test case for git fetching.

This commit is contained in:
Todd Gamblin 2014-10-01 23:32:36 -07:00
parent c74cd63389
commit da84764e97
7 changed files with 232 additions and 18 deletions

View file

@ -225,15 +225,14 @@ def __init__(self, name, *rev_types, **kwargs):
"%s requires %s argument." % (self.__class__, name))
# Ensure that there's only one of the rev_types
if sum((k in kwargs for k in rev_types)) > 1:
if sum(k in kwargs for k in rev_types) > 1:
raise FetchStrategyError(
"Supply only one of %s to fetch with %s." % (
comma_or(rev_types), name))
# Set attributes for each rev type.
for rt in rev_types:
setattr(self, rt, getattr(kwargs, rt, None))
setattr(self, rt, kwargs.get(rt, None))
def check(self):
assert(self.stage)
@ -301,7 +300,14 @@ def fetch(self):
tty.msg("Already fetched %s." % self.stage.source_path)
return
tty.msg("Trying to clone git repository: %s" % self.url)
args = []
if self.commit:
args.append('at commit %s' % self.commit)
elif self.tag:
args.append('at tag %s' % self.branch)
elif self.branch:
args.append('on branch %s' % self.branch)
tty.msg("Trying to clone git repository:", self.url, *args)
if self.commit:
# Need to do a regular clone and check out everything if
@ -460,4 +466,3 @@ def __init__(self, msg, long_msg):
class InvalidArgsError(FetchStrategyError):
def __init__(self, msg, long_msg):
super(InvalidArgsError, self).__init__(msg, long_msg)

View file

@ -372,10 +372,8 @@ def ensure_has_dict(attr_name):
if not hasattr(self, 'url'):
self.url = None
# Set up a fetch strategy for this package.
self.fetcher = None
if self.spec.concrete:
self.fetcher = fs.from_args(self.versions[self.version], self)
# Init fetch strategy to None
self._fetcher = None
# Set a default list URL (place to find available versions)
if not hasattr(self, 'list_url'):
@ -458,6 +456,21 @@ def stage(self):
return self._stage
@property
def fetcher(self):
if not self.spec.concrete:
raise ValueError("Can only get a fetcher for a concrete package.")
if not self._fetcher:
self._fetcher = fs.from_args(self.versions[self.version], self)
return self._fetcher
@fetcher.setter
def fetcher(self, f):
self._fetcher = f
def mirror_path(self):
"""Get path to this package's archive in a mirror."""
filename = "%s-%s." % (self.name, self.version)

View file

@ -47,10 +47,10 @@
def _autospec(function):
"""Decorator that automatically converts the argument of a single-arg
function to a Spec."""
def converter(self, spec_like):
def converter(self, spec_like, **kwargs):
if not isinstance(spec_like, spack.spec.Spec):
spec_like = spack.spec.Spec(spec_like)
return function(self, spec_like)
return function(self, spec_like, **kwargs)
return converter
@ -63,10 +63,14 @@ def __init__(self, root):
@_autospec
def get(self, spec):
def get(self, spec, **kwargs):
if spec.virtual:
raise UnknownPackageError(spec.name)
if kwargs.get('new', False):
if spec in self.instances:
del self.instances[spec]
if not spec in self.instances:
package_class = self.get_class_for_package_name(spec.name)
try:
@ -77,6 +81,17 @@ def get(self, spec):
return self.instances[spec]
@_autospec
def delete(self, spec):
"""Force a package to be recreated."""
del self.instances[spec]
def purge(self):
"""Clear entire package instance cache."""
self.instances.clear()
@_autospec
def get_installed(self, spec):
"""Get all the installed specs that satisfy the provided spec constraint."""

View file

@ -47,7 +47,8 @@
'package_sanity',
'config',
'directory_layout',
'python_version']
'python_version',
'git_fetch']
def list_tests():

View file

@ -0,0 +1,175 @@
##############################################################################
# Copyright (c) 2013, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
#
# This file is part of Spack.
# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
# For details, see https://scalability-llnl.github.io/spack
# Please also see the LICENSE file for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License (as published by
# the Free Software Foundation) version 2.1 dated February 1999.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
# conditions of the GNU General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
import os
import unittest
import shutil
import tempfile
from contextlib import closing
from llnl.util.filesystem import *
import spack
from spack.version import ver
from spack.stage import Stage
from spack.util.executable import which
from spack.test.mock_packages_test import *
test_repo_path = 'test-repo'
test_file_name = 'test-file.txt'
test_branch = 'test-branch'
test_branch_file_name = 'branch-test-file'
test_tag_branch = 'test-tag-branch'
test_tag = 'test-tag'
test_tag_file_name = 'tag-test-file'
untracked = 'foobarbaz'
git = which('git', required=True)
def rev_hash(rev):
return git('rev-parse', rev, return_output=True).strip()
class GitFetchTest(MockPackagesTest):
"""Tests fetching from a dummy git repository."""
def setUp(self):
"""Create a git repository with master and two other branches,
and one tag, so that we can experiment on it."""
super(GitFetchTest, self).setUp()
self.stage = Stage('fetch-test')
self.repo_path = join_path(self.stage.path, test_repo_path)
mkdirp(self.repo_path)
self.test_file = join_path(self.repo_path, test_file_name)
touch(self.test_file)
with working_dir(self.repo_path):
git('init')
git('add', self.test_file)
git('commit', '-m', 'testing')
git('branch', test_branch)
git('branch', test_tag_branch)
git('checkout', test_branch)
touch(test_branch_file_name)
git('add', test_branch_file_name)
git('commit', '-m' 'branch test')
git('checkout', test_tag_branch)
touch(test_tag_file_name)
git('add', test_tag_file_name)
git('commit', '-m' 'tag test')
git('tag', test_tag)
git('checkout', 'master')
self.commit = rev_hash(test_tag)
spec = Spec('git-test')
spec.concretize()
self.pkg = spack.db.get(spec, new=True)
def tearDown(self):
"""Destroy the stage space used by this test."""
super(GitFetchTest, self).tearDown()
if self.stage is not None:
self.stage.destroy()
self.pkg.do_clean_dist()
def assert_rev(self, rev):
"""Check that the current git revision is equal to the supplied rev."""
self.assertEqual(rev_hash('HEAD'), rev_hash(rev))
def try_fetch(self, rev, test_file, args):
"""Tries to:
1. Fetch the repo using a fetch strategy constructed with
supplied args.
2. Check if the test_file is in the checked out repository.
3. Assert that the repository is at the revision supplied.
4. Add and remove some files, then reset the repo, and
ensure it's all there again.
"""
self.pkg.versions[ver('git')] = args
self.pkg.do_stage()
self.assert_rev(rev)
file_path = join_path(self.pkg.stage.source_path, test_file)
self.assertTrue(os.path.isdir(self.pkg.stage.source_path))
self.assertTrue(os.path.isfile(file_path))
os.unlink(file_path)
self.assertFalse(os.path.isfile(file_path))
touch(untracked)
self.assertTrue(os.path.isfile(untracked))
self.pkg.do_clean_work()
self.assertFalse(os.path.isfile(untracked))
self.assertTrue(os.path.isdir(self.pkg.stage.source_path))
self.assertTrue(os.path.isfile(file_path))
self.assert_rev(rev)
def test_fetch_master(self):
"""Test a default git checkout with no commit or tag specified."""
self.try_fetch('master', test_file_name, {
'git' : self.repo_path
})
def test_fetch_branch(self):
"""Test fetching a branch."""
self.try_fetch(test_branch, test_branch_file_name, {
'git' : self.repo_path,
'branch' : test_branch
})
def test_fetch_tag(self):
"""Test fetching a tag."""
self.try_fetch(test_tag, test_tag_file_name, {
'git' : self.repo_path,
'tag' : test_tag
})
def test_fetch_commit(self):
"""Test fetching a particular commit."""
self.try_fetch(self.commit, test_tag_file_name, {
'git' : self.repo_path,
'commit' : self.commit
})

View file

@ -101,13 +101,8 @@ def test_install_and_uninstall(self):
self.assertTrue(spec.concrete)
# Get the package
print
print "======== GETTING PACKAGE ========"
pkg = spack.db.get(spec)
print "======== GOT PACKAGE ========"
print
# Fake the URL for the package so it downloads from a file.
archive_path = join_path(self.stage.path, archive_name)
pkg.fetcher = URLFetchStrategy('file://' + archive_path)

View file

@ -0,0 +1,10 @@
from spack import *
class GitTest(Package):
"""Mock package that uses git for fetching."""
homepage = "http://www.git-fetch-example.com"
version('git', git='to-be-filled-in-by-test')
def install(self, spec, prefix):
pass